【模式設計】03 Template Mathod(“組件協作”模式一)

“組件協作“模式:現代軟件專業分工之後的第一個結果是“框架與應用程序的劃分”,“組件協作”模式通過晚期綁定,來實現框架與應用程序之間的松耦合,是二者之間協作時常用的模式。

****注:Template Mathod 是一種非常基礎性的設計模式,面向對象中,它的核心是動態。有時候可以斷言,如果寫給面向對象的代碼那必定用到模板方法,反正,你寫的就不是面向對象的代碼了。

模式設計一些理論分類

模式分類:

從目的來看:
• 創建型(Creational)模式:將對象的部分創建工作延遲到子類或者其他對象,從而應對需求變化爲對象創建時具體類型實現引來的衝擊。
• 結構型(Structural)模式:通過類繼承或者對象組合獲得更靈活的結構,從而應對需求變化爲對象的結構帶來的衝擊。
• 行爲型(Behavioral)模式:通過類繼承或者對象組合來劃分類與對象間的職責,從而應對需求變化爲多個交互的對象帶來的衝擊。
從範圍來看:
• 類模式處理類與子類的靜態關係。
• 對象模式處理對象間的動態關係。
在這裏插入圖片描述

重構獲得模式 Refactoring to Patterns

面向對象設計模式是“好的面向對象設計”,所謂“好的面向對象設計”指是那些可以滿足 “應對變化,提高複用”的設計 。

現代軟件設計的特徵是“需求的頻繁變化”。設計模式的要點是“尋找變化點,然後在變化點處應用設計模式,從而來更好地應對需求的變化”.“什麼時候、什麼地點應用設計模式”比“理解設計模式結構本身”更爲重要。

設計模式的應用不宜先入爲主,一上來就使用設計模式是對設計模式的最大誤用。沒有一步到位的設計模式。敏捷軟件開發實踐提倡的“Refactoring to Patterns”是目前普遍公認的最好的使用設計模式的方法。

設計模式必須有一個必要條件,必須有一個穩定,不然沒法進行設計。(尋求變化與穩定的關係)
假設所有東西都不穩定,那設計模式沒意義了。

重構關鍵技法

靜態 ----》》 動態(或者靜態綁定變動態綁定)

早綁定 ----》》 晚綁定

繼承 ----》》 組合

編譯時依賴 ----》》 運行時依賴

緊耦合 ----》》松耦合

Template Method 模式

動機(Motivation)

在軟件構建過程中,對於某一項任務,它常常有穩定的整體操作結構,但各個子步驟卻有很多改變的需求,或者由於固有的原因(比如框架與應用之間的關係)而無法和任務的整體結構同時實現。

下面講一下:如何在確定穩定操作結構的前提下,來靈活應對各個子步驟的變化或者晚期實現需求?

結構化軟件設計流程

在這裏插入圖片描述
僞代碼03:
這是一個程序庫開發人員和應用程序開發人員,對流程步驟程序的一個編碼例子:

//程序庫開發人員
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();
////////////////////////////////////////////////////////////////////
}

如上兩個代碼 先有的程序庫開發人員寫出了父類步驟1、3、5,後有 app開發人員寫出的子類步驟2、4。並且逼得APP開發人員還得寫主調用程序。這就是結構化軟件設計流程,讓後有的程序去調用早有的程序(這就叫做早綁定)。而一般面向對象的開發中,APP 開發人員是不用寫主調用程序(框架)的,甚至於main程序都不用寫,僅僅是進調用鏈接而已。

那我們要做優化 ,要將模式設計中的模板方法用到,這個僞代碼中,怎麼來實現?
答案就是:將早綁定 改變成晚綁定

寫的晚的調用早的叫做早綁定;一個早的調用晚的叫做晚綁定

面向對象軟件設計流程

在這裏插入圖片描述

僞代碼 04

//程序庫開發人員
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;
	}
}

如上僞代碼:我們將步驟2、4設置成純虛函數,並且程序庫開發人員寫好了主調用程序,這個主調用程序就是模板方法。通過將其他變化的函數設置成虛函數,在父類中編寫主調用函數,然後通過在主調用函數中調用虛函數,來實現晚綁定。

在C++中晚綁定機制有:虛函數是最常用的 還有函數指針。(函數指針基本不用了,不如虛函數抽象,但是反過來想一下,虛函數不就是虛函數表裏裝的函數指針嘛。)

模式定義

定義一個操作中的算法的骨架 (穩定),而將一些步驟延遲(變化)到子類中。Template Method使得子類可以不改變(複用)一個算法的結構即可重定義(override 重寫)該算法的某些特定步驟。
——《設計模式》GoF

要點總結

Template Method模式是一種非常基礎性的設計模式,在面向對象系統中有着大量的應用。它用最簡潔的機制(虛函數的多態性)爲很多應用程序框架提供了靈活的擴展點,是代碼複用方面的基本實現結構。(什麼叫擴展:繼承+多態)

除了可以靈活應對子步驟的變化外,“不要調用我,讓我來調用你”的反向控制結構是Template Method的典型應用。

在具體實現方面,被Template Method調用的虛方法可以具有實現,也可以沒有任何實現(抽象方法、純虛方法),但一般推薦將它們設置爲protected方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章