模板方法模式——Template Method Pattern
阿新 • • 發佈:2019-01-04
模板方法模式
模擬製作飲料的應用:
在沖泡飲料時,我們需要遵循下面的沖泡步驟,即
(1)把水煮沸
(2)用沸水沖泡
(3)把沖泡後的飲料倒進杯子
(4)加入適當的調料
另外,對於不同的飲料,步驟(2)的沖泡方法和步驟(4)的加入調料的方法是不同的
因此需要將這兩個方法設計為抽象方法,程式碼如下:
為了解決這個問題,我們可以將製作飲料的四個步驟寫在一個方法裡面,程式碼如下:
模板方法模式:在一個方法中定義一個演算法的骨架,而將一些步驟延遲到子類中
子類可以在不改變演算法結構的情況下,重新定義演算法中的某些步驟
程式碼演示:
那麼,上例中的第個四步驟並不是必須的,這時我們就要加入一個判斷語句:
為了解決這個問題,我們需要對模板方法進行掛鉤,即使用鉤子方法
上例中的isCustomerWantsCondiments()就是一個鉤子
Swing窗體例項:
模板方法定義了演算法的步驟,並把這些步驟的實現延遲到子類
模板方法的抽象類可以定義具體方法,抽象方法和鉤子方法
抽象方法是可變步驟,由子類實現
鉤子方法可以控制某些步驟是否需要執行
模板方法用於封裝演算法並實現程式碼的複用
參考書籍《Head First 設計模式》
模擬製作飲料的應用:
在沖泡飲料時,我們需要遵循下面的沖泡步驟,即
(1)把水煮沸
(2)用沸水沖泡
(3)把沖泡後的飲料倒進杯子
(4)加入適當的調料
另外,對於不同的飲料,步驟(2)的沖泡方法和步驟(4)的加入調料的方法是不同的
因此需要將這兩個方法設計為抽象方法,程式碼如下:
我們有兩種飲料需要使用這個沖泡飲料的方法,茶和咖啡,程式碼如下:public abstract class Beverage { void boilWater() { System.out.println("Boiling water."); } //(1)把水煮沸 void pourInCup() { System.out.println("Pouring into cup.") } //(3)把飲料倒進杯子 abstract void brew(); //(2)用沸水沖泡 abstract void addCondiments(); //(4)加入適當的調料 }
public class Tea extends Beverage
{
public void brew()
{
System.out.println("Steeping the tea.");
}//浸泡茶葉
public void addCondiments()
{
System.out.println("Adding Lemon.");
}//加入檸檬
}
現在我們可以來製作茶和咖啡了,程式碼如下:public class Coffee extends Beverage { public void brew() { System.out.println("Dripping Coffee through filter."); }//沖泡咖啡 public void addCondiments() { System.out.println("Adding Sugar and Milk."); }//加入糖和牛奶 }
public class MarkBeverage
{
Tea tea = new Tea();
tea.boilWater();
tea.brew();
tea.pourInCup();
tea.addCondiments();
Coffee coffee = new Coffee();
coffee.boilWater();
coffee.brew();
coffee.pourInCup();
coffee.addCondiments();
}
一切看起來都很正常,可是,如果要新建多個物件,那麼我們就要寫多個方法呼叫為了解決這個問題,我們可以將製作飲料的四個步驟寫在一個方法裡面,程式碼如下:
public abstract class Beverage
{
void make()
{
boilWater(); //(1)把水煮沸
brew(); //(2)用沸水沖泡
pourInCup(); //(3)把飲料倒進杯子
addCondiments(); //(4)加入適當的調料
}
void boilWater()
{
System.out.println("Boiling water.");
} //(1)把水煮沸
void pourInCup()
{
System.out.println("Pouring into cup.")
} //(3)把飲料倒進杯子
abstract void brew(); //(2)用沸水沖泡
abstract void addCondiments(); //(4)加入適當的調料
}
這樣做看起來清晰多了,使用時也變得相對簡單,而且也達到了封裝的效果:public class MarkBeverage
{
Tea tea = new Tea();
tea.mark();
Coffee coffee = new Coffee();
coffee.mark();
}
這就是模板方法模式模板方法模式:在一個方法中定義一個演算法的骨架,而將一些步驟延遲到子類中
子類可以在不改變演算法結構的情況下,重新定義演算法中的某些步驟
程式碼演示:
public abstract class AbstractClass
{
final void templateMethod
{
methodOne();
methodTwo();
/*------第N個普通方法------*/
abstractMethodOne();
abstractMethodTwo();
/*------第N個抽象方法------*/
}
//不需要改變的步驟使用final宣告
final void methodOne(){}
final void methodTwo(){}
//可改變的步驟宣告為抽象方法,在子類裡重新定義
abstract abstractMethodOne();
abstract abstractMethodTwo();
}
另外,需要考慮到其它的一些情況,如,並不是所有人都會喝加牛奶的咖啡那麼,上例中的第個四步驟並不是必須的,這時我們就要加入一個判斷語句:
public abstract class Beverage
{
void make()
{
boilWater(); //(1)把水煮沸
brew(); //(2)用沸水沖泡
pourInCup(); //(3)把飲料倒進杯子
if(isCustomerWantsCondiments())
{
addCondiments(); //(4)加入適當的調料
}
}
void boilWater()
{
System.out.println("Boiling water.");
} //(1)把水煮沸
void pourInCup()
{
System.out.println("Pouring into cup.")
} //(3)把飲料倒進杯子
boolean isCustomerWantsCondiments()
{
return true;
}//新加入的方法,用於判斷是否加調料
abstract void brew(); //(2)用沸水沖泡
abstract void addCondiments(); //(4)加入適當的調料
}
現在我們知道了並不總是使用模板方法中的所有方法為了解決這個問題,我們需要對模板方法進行掛鉤,即使用鉤子方法
上例中的isCustomerWantsCondiments()就是一個鉤子
Swing窗體例項:
//此處省略import語句
public class MyFrame extends JFrame
{
//update()方法為模板方法Template method
public MyFrame(String title)
{
super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(300,300);
}//初始化窗體
public void paint(Graphics graphics)
{
super.paint(graphics);
graphics.drawString("Hello",100,100);
}//paint()方法為鉤子方法Hook method
public static void main(String args[])
{
MyFrame frame = new MyFrame("Hello!");
}
}
模板方法定義了演算法的步驟,並把這些步驟的實現延遲到子類
模板方法的抽象類可以定義具體方法,抽象方法和鉤子方法
抽象方法是可變步驟,由子類實現
鉤子方法可以控制某些步驟是否需要執行
模板方法用於封裝演算法並實現程式碼的複用
參考書籍《Head First 設計模式》