Contents

Design Pattern Oop

  • 每個 class 單一職責,例如有一個 Journal class 負責日記的資料結構,如果要加入儲存功能,要另外設計 JournalManager class 而不是直接加在裡面,可以做到儲存的抽象化、模組化
  • C++ 問題
    • explicit class member function
  • 對 class 開放擴充,關閉修改
  • 要符合 subtype 的規則,否則不能使用繼承,使用繼承會造成不可預測的結果
    • 若 A 不是 B 的 subtype,A 就不應該繼承自 B,例如 B 是長方形,提供 set_width()set_height(),此時 A 是正方形,因為繼承後,正方形的 set_width()set_height() 分別執行後,會造成結果與長方形的預期不同
  • Subtype Relation lsp-def.jpg
    • Covariance of arguments
      • Contravariance of method parameter types in the subtype.
    • Covariance of result
      • Covariance of method return types in the subtype.
    • Exception rule
      • New exceptions cannot be thrown by the methods in the subtype, except if they are subtypes of exceptions thrown by the methods of the supertype.
    • Pre-condition rule
      • Preconditions cannot be strengthened in the subtype.
    • Post-condition rule
      • Postconditions cannot be weakened in the subtype.
    • Invariant rule
      • Invariants must be preserved in the subtype.
    • Constraint rule
      • Subtype constraints ensure supertype constraints.
  • 介面只要有需要的,而不是包山包海,若留下來的代表是要實作,去掉可能不會實作的介面
  • High-level module 的實作不該依賴 low-level module 的實作,兩者只該依賴抽象介面
  • 介面不該依賴實作,實作才該依賴介面

/design-pattern-oop/catalog.png

  • Inheritance: subclass 透過繼承 parent class,來達到 Reusability
    • 優點:
      • 在 compile-time 就定義好 implementation,執行速度較快
      • 簡單就能重複使用 parent class 的內容
    • 缺點:
      • 無法在 run-time 決定 implementation,彈性較低
      • 繼承 parent class 所有內容,破壞封裝的原則,當 parent class 修改實作,subclass 就會跟著被迫改變,導致彈性低、降低重複使用性
  • Object Composition: subclass 僅繼承介面,在 run-time 決定實作的 object
    • 優點:
      • 只繼承介面,不會破壞封裝原則,彈性較高
      • 不會造成複雜的繼承關係,較容易管理
      • 較容易設計出,每個物件單一職責
    • 缺點:
      • 要特別注意介面的設計,因為不能常改動
      • 容易產生多個 object,要特別注意 object 之間的關係,object 之間要如何互動
  • Delegation: 目的在於將 composition 接近 inheritance 的方便性。通常的做法是在 class 中擁有要 delegate 的 instance
    • 優點:
      • 如果要 delegate 的對象有相同的 type (繼承相同的介面),可以在 run-time 替換
    • 缺點
      • highly parameterized 的軟體較難理解,較適合簡單的情境
      • 要有比較多的經驗來判斷是否適合使用 delegation,優先考慮標準的 pattern,例如: StateStrategyVisitor
  • Parameterized Type: 在 compile-time 將 type 當作參數建立 object
    • GoF 介紹的 design pattern 不會使用此技術
  • 減少修改後的後果,確保使用特定的方式修改
  • 以下列出各種設計缺失與對應的 pattern
    • 使用特定的 class 建立 object
      • 避免原因: 當 object 變多,統一建立 object 的方法,降低建立 object 的複雜度
      • 相關 patterns: Abstract FactoryFactory MethodPrototype
    • 依賴於特定的 operation
      • 避免原因: operation 互相依賴,避免 hard-coded request,降低加入其他 operation 的複雜度
      • 相關 patterns: Chain of ResponsibilityCommand
    • 依賴於硬體或軟體平台
      • 避免原因: 若依賴於特定平台,會難維護與升級,要降低系統依賴
      • 相關 patterns: Abstract FactoryBridge
    • 依賴於 object 內部行為與實作
      • 避免原因: 當 object 內部修改,若依賴內部實作,client 需要重新修改
      • 相關 patterns: Abstract FactoryBridgeMementoProxy
    • 依賴於演算法內部實作
      • 避免原因: 在開發中演算法常常會擴充、最佳化、重複使用,若依賴內部實作,當演算法內部修改,client 需要重新修改
      • 相關 patterns: BridgeIteratorStrategyTemplate MethodVisitor
    • 緊密耦合
      • 避免原因: 耦合程度高,造成 monolithic system,難以修改、維護、學習,使用 abstract coupling、layering 降低耦合
      • 相關 patterns: Abstract FactoryBridgeChain of ResponsibilityCommandFacadeMediatorObserver
    • 使用繼承實作來擴充功能
      • 避免原因: 需要理解 parent class 的內部實作,可能會不必要的覆蓋 parent class 的實作。比較好的做法是,只繼承介面
      • 相關 patterns: BridgeChain of ResponsibilityCompositeDecoratorObserverStrategy
    • 無法方便的修改 class
      • 避免原因: 可能會造成修要修改一堆 subclass
      • 相關 patterns: AdapterDecoratorVisitor
  • 設計重點: 考慮 object 在內部重複使用、維護性、擴充性
  • Design Pattern 解決方式: 降低耦合、封裝和獨立單一功能
  • Toolkit: 提供給 Application 的 general purpose 函示庫,例如 C++ STL
  • 設計重點: 提供 general purpose 介面、提供給 Application 容易使用且彈性
  • Framework: 提供給 Application 架構的 specific domain 函示庫,例如 Qt
  • 設計重點: 提供架構設計的重複使用、文件說明架構與使用的 pattern

/design-pattern-oop/aggregation.jpg

  • Aggregation: object 負責其 aggregate object 的一部分功能,每個相關的 object 都有獨立的 lifetime。例如,在 C++ 中的 member variables 聚合而成 aggregation object
  • Acquaintance (aka Association、Using relationship): 較弱的關係,object 之間不互相負責,較容易變動。例如,在 C++ 中的 member variables (通常是 pointer 或 reference),且可能在 run-time 指向其他 instance
  • 有些 design patterns 特別設計在 compile-time 和 run-time 的架構,例如,CompositeDecorator 特別用在建構複雜的 run-time 架構;Observer 參與 run-time 時的架構;Chain of Responsibility 在繼承物件之間溝通
  • run-time 架構,若不知道相關的模式會較難理解
  • 大方向了解 Creational、Structural、Behavioral 分別的用處
  • 參考 GoF Chapter 1.4 對各 Pattern 的概述
  • 思考模組之間如何互動,參考 Pattern 之間的關聯 /design-pattern-oop/design-pattern-relationship.jpg
  • 思考如何避免將來的重新設計
  • 思考將來可能會有甚麼改變
  • 常見的用法 /design-pattern-oop/design-aspect.jpg
  • Creational Pattern 對 class 的 Realization 的過程進行抽象,能將 Module 的創建和使用分離
  • 模式動機: 想使用特定的子類別,但不想用該子類別的名字,而用父類別的名字加上特定參數
  • 模式定義: 又稱 Static Factory Method。定義一個 class,根據參數返回特定 class 的 instance,被創建的 class 通常有相同的父類別
  • 適用情況: 產生的 class 種類較少
  • 模式動機: 不設計一個統一的工廠來負責所有產品的創建,能將工廠和產品抽象化
  • 模式定義: 工廠父類別負責定義創建產品的介面,產生統一的產品介面,需要再個別對工廠和產品實作
  • 適用情況: 不需要知道產品類別名,也可以不需要知道對應的工廠類別名 (需要時再動態指定),產品等級結構單一
  • 實際應用: JDBC
1
2
3
4
Connection conn=DriverManager.getConnection("jdbc:microsoft:sqlserver://loc
alhost:1433; DatabaseName=DB;user=sa;password=");
Statement statement=conn.createStatement();
ResultSet rs=statement.executeQuery("select * from UserInfo");
  • 模式動機: 工廠往往會產生多種不同等級結構和產品族,例如鴻海工廠,生產不同品牌的手機 (不同等級結構),生產不同的電器 (不同產品族),Factory Method 無法有效率的處理
  • 模式定義: 又稱作 Kit 模式。工廠提供生產某產品族 (手機) 的介面,根據不同的等級結構 (Google 品牌) 各別實作對應的工廠,產生出特定的產品
  • 適用情況:
    • 系統有多個產品族,每次只使用其中每一產品族
    • 同產品族的產品會一起使用
  • 實際應用: 更換桌面主題,相關的按鈕、背景等一起改變

實作練習


  • C++ 問題
    • static function
    • unique_ptr 使用 get 的行為? 使用 Sigleton 時,要回傳 pointer、smart pointer、reference?
  • C++ 問題
    • :: 與 lambda 的用法?
    • lambda 中 capture, parameter 的差異
  • C++ 問題
    • delete default final member function
    • private default constructor
    • friend member in class
    • protected member in class
    • 繼承 template class
  • is a static factory method
  • 避免 hardcoding class name,常見的做法是,factory 根據參數回傳 derived class instance
  • registry based factory
  • C++
    • 繼承 Factory base class,使用 template class 來包裝成 ConcreteFactory,當使用此 template 就會自動註冊新的 ConcreteFactory instance 到 Factory 的 static map
    • 使用 Anonymous namespace 來宣告不能直接存取的 static object
    • 使用 macro 來註冊 ConcreteFactory instance
  • 跟 GoF 的 builder pattern 不同
  • UserData 和 UserBuilder 分離,Builder 提供建立資料的介面,回傳 Data
  • C++
    • friend class in public section
    1
    2
    3
    4
    5
    
    class UserData {
    public: 
      // Allow builder class access UserData's private data
      friend class UserBuilder;
    };
    
    • 可以直接使用 UserBuilder() 而沒有建立 instance?
  • 方便在既有的 Component 擴充功能,而不修改 Component Class
  • Component 的共同屬性獨立出來,放在 Decorator 中,Decorator 可修改不同種 Component 特定的屬性
  • C++
    • Decorator 會擁有 Component 的 shared_ptr
    • make_shared 與繼承的關係?
    • []{}() 是甚麼?

  • 模式動機:
  • 模式定義:
  • 適用情況:
  • 實際應用:

實作練習





Комментарии