設計模式的學習方法:
知道在什麼時候,什麼地方使用設計模式,比理解設計模式結構本身更加重要。
設計模式的三階段:
不會設計模式 ---->濫用設計模式---->會用設計模式
重構的關鍵技法:
-
靜態--->動態
-
早綁定--->晚綁定
-
繼承--->組合
-
編譯時依賴--->運行時依賴
-
緊耦合--->松耦合
組件協作模式:
組件協作模式通過晚期綁定,來實現框架與應用程序之間的松耦合,是二者之間協作常用的模式。
典型的有:
- Template Method(模板方法)
- Strategy(策略模式)
- Observer/Event(事件模式)
Template Method
動機
- 在軟件構建的過程中,對某一項任務,它常常有穩定的整體操作結構,但各個子步驟卻有很多改變的需求,或者由於固有的原因(比如框架與應用之間的關係)而無法和任務的整體結構同時實現。
- 如何在確定穩定操作結構的前提下,來靈活應對各個子步驟的變化或者晚期實現需求。
例如有一個程序庫開發人員設計了一個Library類,它實現了三種方法,代碼如下:
#ifndef LIBRARY_H
#define LIBRARY_H
class Library{
public:
void Step1(){
//...
}
void Step3(){
//...
}
void Step5(){
//...
}
};
#endif
而應用程序開發人員要實現這個任務的話,他可能會編寫以下代碼
#ifndef APPLICATION_H
#define APPLICATION_H
class Application{
public:
void Step2(){
//...
}
void Step4(){
//...
}
};
#endlif
進行以下調用(這個調用類似於一些框架的生命週期,必須得如此調用)
#include <iostream>
#include "Application.h"
#include "Library.h"
int main(int argc, char** argv) {
Library lib();
Application app();
lib.Step1();
if(app.Step2()){
lib.Step3();
}
for(int i = 0; i < 4; i++){
app.Step4();
}
lib.Step5();
}
我們發現這個設計的糟糕之處就是,無論是誰來使用Library類都必須重複實現main函數裏面的步驟。
我們可以做出如下改進:
#ifndef LIBRARY_H
#define LIBRARY_H
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;//變化
};
#endif
然後讓Application繼承Library,並實現虛函數
#ifndef APPLICATION_H
#define APPLICATION_H
#include"Library.h"
class Application : public Library{
public:
bool Step2(){
//...
}
void Step4(){
//...
}
};
#endif
這個時候應用程序開發人員無需知道整個代碼書寫流程,只要實現相關虛函數並調用run方法就可以使用,main函數如下:
#include <iostream>
#include "Application.h"
int main(int argc, char** argv) {
Library *pLib = new Application();
pLib->Run();
return 0;
}
流程如下
分析兩種寫法
- 第一種寫法就是典型的早綁定當程序庫開發人員提前寫好Library庫時,應用程序開發人員再在此基礎上經行編寫代碼。Library是早出現的,Application是晚出現的,由晚出現調用早出現的就叫早綁定;
- 第二種寫法是典型的晚綁定,Library是早出現的,Application是晚出現的,由早出現調用晚出現的就叫晚綁定;
模式的定義
定義一個操作中的算法骨架(穩定),而將一些步驟延遲(變化)到子類中。Template Method使得子類可以不改變(複用)一個算法的結構即可重定義(override重寫)該算法的某些特定步驟。
缺點
必須有一個穩定的算法骨架,如代碼中的Run()方法。這也就是設計模式在穩定中平衡變化的特點。