Einar Landre

封裝的層次#

在**系統理論(systems theory)**中,**封裝(containment)**是處理大型複雜系統結構最有用的構造之一。在軟體產業中,封裝的價值被廣泛認可,並由程式語言中的各種構造支持:副程式、函式、模組、套件、類別等。

  • 模組和套件處理較大規模的封裝需求
  • 類別、副程式和函式處理較細粒度的部分

然而,多年來作者發現類別是開發者最難正確使用的封裝構造。常見的錯誤包括:一個類別有一個 3,000 行的 main 方法,或者一個類別只有 setget 方法來存取原始屬性。

物件封裝行為與狀態#

物件同時封裝狀態(state)行為(behavior),其中行為由實際狀態定義。考慮一個門(door)物件,它有四種狀態:closed、open、closing、opening,並提供兩種操作:open 和 close。

這種將行為與狀態綁定的特性讓設計過程概念上非常簡單,歸結為兩個任務:

  • 職責分配(allocation of responsibility)
  • 職責委派(delegation of responsibility),包括物件間的互動協議

實際範例:訂單系統#

假設有三個類別:CustomerOrderItem

  • Customer 是信用額度和信用驗證規則的天然持有者
  • Order 知道其關聯的 Customer,其 addItem 操作透過呼叫 customer.validateCredit(item.price()) 來委派實際的信用檢查
  • 如果後置條件失敗,就拋出例外並中止購買

反面模式:打破封裝#

經驗較少的物件導向開發者可能會將所有商業規則塞進一個物件,通常稱為 OrderManagerOrderService。在這種設計中,OrderCustomerItem 被當作不過是記錄型別(record types)。所有邏輯從各類別中抽出,塞進一個大型的程序式方法中,充滿 if-then-else 結構。

這些方法極易出錯且幾乎不可能維護。原因就是封裝被破壞了

不要打破封裝——善用你的程式語言的力量來維護它。讓每個物件擁有自己的行為,而不僅僅是資料。