1、無處不在的Template Method
1)若是你只想掌握一種設計模式,那麼它就是Template Method模式!
2)變與不變
變化——是軟件設計的永恆主題,如何管理變化帶來的複雜性?設計模式的藝術和複雜度就在於如何分析,並發現系統中的變化點和穩定點,並使用特定的設計方法來應對這種變化。
2、動機(Motivation)
1)在軟件構建過程當中,對於某一項任務,它經常有穩定的總體操做結構,但各個子步驟卻有不少改變的需求,或者因爲固有的緣由(好比框架與應用之間的關係)而沒法和任務的總體結構同時實現。
2)如何在肯定穩定操做結構的前提下,來靈活應對各個子步驟的變化或者晚期實現需求?
3、意圖(Intent)
定義一個操做中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。
——《設計模式》GoF
4、實例:汽車測試軟件(計算機模擬環境)
//框架開發者-先開發
public abstract class Vehical //汽車抽象類
{
//啓動
protected abstract void StartUp();
//跑動
protected abstract void Run();
//轉彎,參數,角度
protected abstract void Turn(int degree);
//中止
protected abstract void Stop();
//測試
public void Test()
{
//...測試數據記錄
StartUp(); //晚綁定-留給應用程序開發人員來作:擴展點
//...測試數據記錄
Run(); //晚綁定-留給應用程序開發人員來作:擴展點
//...測試數據記錄
Turn(1); //晚綁定-留給應用程序開發人員來作:擴展點
//...測試數據記錄
Stop(); //晚綁定-留給應用程序開發人員來作:擴展點
//...測試數據記錄
//......
//...生成測試報表
}
}算法
//測試汽車
public class VehicalTestFramework
{
public static void DoTest(Vehical vehical)
{
vehical.Test();
}
}設計模式
//應用程序開發人員-晚開發
public class HongQiCar : Vehical //紅旗汽車
{
protected override void StatrUp()
{
//......
}
protected override void Run()
{
//......
}
protected override void Turn(int degree)
{
//......
}
protected override void Stop()
{
//......
}
}併發
//客戶程序
class App
{
public static void Main()
{
VehicalTestFramework.DoTest(new HongQiCar());
}
}框架
5、Template Method模式的幾個要點
1)Template Method模式是一種很是基礎性的設計模式,在面向對象系統中有着大量的應用。它用量簡潔的機制(虛函數的多態性)爲不少應用程序框架提供了靈活的擴展點,是代碼複用方面的基本實現結構。
2)除了能夠靈活應對子步驟的變化外,「不要調用我,讓我來調用你」的反向控制結構是Template Method的典型應用。
3)在具體實現方面,被Template Method調用的虛方法能夠具備實現,也能夠沒有任何實現(抽象方法、純虛方法),但通常推薦將它們設置爲protected方法。ide
6、Template Method模式在.NET框架中的應用
在.NET框架中,Form下的OnPaint方法等On打頭的一些方法,都應用到了模板方法設計模式。函數
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;測試
public class Test
{
public static void Main()
{
Application.Run(new MainForm());
}
}設計
public class MainForm : Form
{
protected override void OnPaint(PaintEventArgs args)
{
Graphics grfx = args.Graphics;
int cx = 300;
int cy = 160;
Point[] apt = new Point[5];
for (int i = 0; i < apt.Length; i++)
{
double dAngle = (i * 0.8 - 0.5) * Math.PI;
apt[i] = new Point((int)(cx * (0.25 + 0.24 * Math.Cos(dAngle))),
(int)(cy * (0.50 + 0.48 * Math.Sin(dAngle))));
}
grfy.FillPolygon(new SolidBrush(Color.Red), apt, FillMode.Winding);
}
}orm