GOF-23 模式分類
- 從目的來看
- 創建型(Creational)模式:將對象的部分創建工作延遲到子
類或者其他對象,從而應對需求變化爲對象創建時具體類型實
現引來的衝擊。 - 結構型(Structural)模式:通過類繼承或者對象組合獲得更靈活的結構,從而應對需求變化爲對象的結構帶來的衝擊。
- 行爲型(Behavioral)模式:通過類繼承或者對象組合來劃分
類與對象間的職責,從而應對需求變化爲多個交互的對象帶來
的衝擊
- 創建型(Creational)模式:將對象的部分創建工作延遲到子
- 從範圍來看
- 類模式處理類與子類的靜態關係。
- 對象模式處理對象間的動態關係。
從封裝變化角度對模式分類
- 組件協作
- Template Method
- Observer / Event
- Strategy
- 單一職責
- Decorator
- Bridge
- 對象創建、
- Factory Method
- Abstract Factory
- Prototype
- Builder
- 對象性能
- Singleton
- Flyweight
- 接口隔離
- Façade
- Proxy
- Mediator
- Adapter
- 狀態變化
- Memento
- State
- 數據結構
- Composite
- Iterator
- Chain of Resposibility
- 行爲變化
- Command
- Visitor
- 領域問題
- Interpreter
重構獲得模式 (Refactoring to Patterns)
- 面向對象設計模式是“好的面向對象設計”,所謂“好的面向對
象設計”指是那些可以滿足 “應對變化,提高複用”的設計 。 - 現代軟件設計的特徵是“需求的頻繁變化”。設計模式的要點是“尋找變化點,然後在變化點處應用設計模式,從而來更好地應對需求的變化”.“什麼時候、什麼地點應用設計模式”比“理解設計模式結構本身”更爲重要。
理清設計中,變化的部分(多態)和固定的部分(抽象)。
- 設計模式的應用不宜先入爲主,一上來就使用設計模式是對設計
模式的最大誤用。沒有一步到位的設計模式。敏捷軟件開發實踐提
倡的“Refactoring to Patterns”是目前普遍公認的最好的使用設
計模式的方法。
相關書籍
重構關鍵技法
- 靜態—>動態
- 早綁定—>晚綁定
(運行時,多態是運行時判斷)
- 繼承—>組合
(組合優於繼承,耦合性低封裝性好且更靈活)
- 編譯時依賴—>運行時依賴
- 緊耦合—>松耦合
------------------------------------------分割線,具體模式的學習-------------------
組件協作模式
- 現代軟件專業分工之後的第一個結果是“框架與應用程序的劃
分”,“組件協作”模式通過晚期綁定,來實現框架與應用程序之
間的松耦合,是二者之間協作時常用的模式。 - 典型模式
- Template Method
- Observer / Event
- Strategy
Template Method 模式
- 動機(Motivation)
- 在軟件構建過程中,對於某一項任務,它常常有穩定的整體操作結構但各個子步驟卻有很多改變的需求,或者由於固有的原因(比如框架與應用之間的關係)而無法和任務的整體結構同時實現。
穩定的部分是整體的操作結構
變化的部分是子步驟的具體操作
所以我們在設計中,將穩定的部分提取出來並抽象。變化的部分,用多態(指針),來保證不同子類不同的操作. - 如何在確定穩定操作結構的前提下,來靈活應對各個子步驟的變
化或者晚期實現需求?
結構化軟件設計流程
//程序庫開發人員
class Library{
public:
void Step1(){
//...
}
void Step3(){
//...
}
void Step5(){
//...
}
};
//應用程序開發人員
class Application{
public:
bool Step2(){
//...
}
void Step4(){
//...
}
};
int main()
{
Library lib();
Application app();
lib.Step1();
if (app.Step2()){
lib.Step3();
}
for (int i = 0; i < 4; i++){
app.Step4();
}
lib.Step5();
}
面向對象軟件設計流程
//程序庫開發人員
class Library{
public:
//穩定 template method
void Run(){
Step1();
if (Step2()) { //支持變化 ==> 虛函數的多態調用
Step3();
}
for (int i = 0; i < 4; i++){
Step4(); //支持變化 ==> 虛函數的多態調用
}
Step5();
}
virtual ~Library(){ }
protected:
void Step1() { //穩定
//.....
}
void Step3() {//穩定
//.....
}
void Step5() { //穩定
//.....
}
virtual bool Step2() = 0;//變化
virtual void Step4() =0; //變化
};
//應用程序開發人員
class Application : public Library {
protected:
virtual bool Step2(){
//... 子類重寫實現
}
virtual void Step4() {
//... 子類重寫實現
}
};
int main()
{
Library* pLib=new Application();
lib->Run();
delete pLib;
}
}
上面兩種設計流程的區別是程序主流程的開發。因爲Library開發人員在設計時,是不清楚2,4兩個步驟的具體操作的,因此這裏就是所謂的變化的部分。對應的邏輯如下圖
早綁定與晚綁定
第一種是由較晚開發的Application去調用庫邏輯,需要在編譯時處理(早綁定),而第二種是,早期開發的Library開發人員,用多態的方式調用2,4(虛函數)。Application人員通過繼承或者組合的方式,override或者overload相應的2,4步驟。從而實現靈活性。所謂的早綁定是編譯時綁定,晚綁定就是運行時綁定。
模式定義
-
定義一個操作中的算法的骨架 (穩定),而將一些步驟延遲(變化)到子類中。Template Method使得子類可以不改變(複用)一個算法的結構即可重定義(override 重寫)該算法的某些特定步驟。
———————《設計模式》GoF -
結構(Structure)
藍色框內爲穩定的部分(Class Library)。
黃色框爲Class Library 的TemplateMethod也就是Class Library中穩定的部分,也就是Class Library 中的Step1,Step3,Step5及Run函數。
紅色框內就是Class Library Step2,Step4(虛函數).
灰色框框內是子類也就是Application.子類重寫黃色框內的Step2,Step4.
要點總結
- Template Method模式是一種非常基礎性的設計模式,在面向對
象系統中有着大量的應用。它用最簡潔的機制(虛函數的多態性)
爲很多應用程序框架提供了靈活的擴展點,是代碼複用方面的基本
實現結構 - 除了可以靈活應對子步驟的變化外,“不要調用我,讓我來調用
你”的反向控制結構是Template Method的典型應用。 - 在具體實現方面,被Template Method調用的虛方法可以具有實
現,也可以沒有任何實現(抽象方法、純虛方法),但一般推薦將
它們設置爲protected方法。