設計模式之生活中的模板模式


在講模板模式原理前,咱們按照管理,先來個生活中例子。茶館須要開發一個自動的泡咖啡和泡茶的程序。java

本文出自:《凱哥學設計模式》系列教程中的模板模式一算法

咱們先來看看泡咖啡和泡茶的步驟:設計模式

document_image_rId9.png

咱們根據上圖寫代碼實現:ide

泡咖啡類,以下圖:測試

document_image_rId10.png

泡茶類以下圖:spa

document_image_rId11.png

測試類:設計

document_image_rId12.png

運行結果:orm

document_image_rId13.png

很簡單。也很容易寫出來。寫出來很清楚。繼承

從上圖中,能夠發現,兩個流程幾乎是同樣的套路(步驟)。其中,不變的部分:水燒開、倒入杯子、送給客人。這三步是不變的。教程

變化的是:衝咖啡仍是泡茶葉;加糖/牛奶仍是加檸檬這兩個步驟是變化的。

項目進化第一個版本:

咱們將不變的抽取出來,放到一個公共的類中。HotDrink。而後讓coffe和tea都繼承公共的類。獲得的類圖以下:

document_image_rId14.png

hotdrink超類代碼以下:

document_image_rId15.png

項目進化第二個版本:

通過分析,咱們發現,兩個流程的還有相同的地方:

1.兩個流程的步驟都同樣(都是五個步驟的);

2.不管泡茶仍是泡咖啡都是brew操做;

3.不管加糖仍是加檸檬都是添加調料的。

因此,咱們對項目在進行一次提取:

咱們將操做流程也提取到超類中,將2和3操做也放到超類中。讓子類具體實現。因此獲得類圖以下:

document_image_rId16.png

咱們來看看此次hotdrink類裏面:

public abstract class HotDrink {

   public final void prepareRecipe(){

       boilWater();

       brew();

       pourInCup();

       addCondiments();

       send();


   }


   protected abstract void addCondiments();


   protected abstract void brew();


   private final void boilWater() {

       System.out.println("一.燒水");

   }

   private final void pourInCup() {

       System.out.println("三.倒入杯中");

   }

document_image_rId17.png

咱們發現,在prepareRecipe方法和boilWter、pourInCup、send這四個操做都添加了final關鍵字來修改。這是爲何呢?

從上面分析,咱們知道,都是五個步驟,並且五個步驟中的三個步驟(燒水、倒入杯中、送客人)也是固定不變的。那麼,在Java中,固定不變的這個怎麼表示呢?對了,就使用fianl這個關鍵字修飾就能夠了。這樣,就能夠放置子類不能隨便修改步驟(好比由五步變成三步),已經規定的不能在修改了。好比燒水這個不燒了,這樣是不行的。

咱們來看看,熱飲coffee和tea的類:

document_image_rId18.png

hotDrinkTea:

document_image_rId19.png

測試方法:

document_image_rId20.png

運行結果:

document_image_rId21.png

咱們對項目進化進行復盤總結,能夠獲得:

所謂的模板模式:封裝了一個算法的步驟,並容許子類爲一個或多個步驟方法提供實現。模板模式,可使子類在不改變算法結構(如上面的五步)的狀況下,從新定義算法中某些步驟(如上面的第二步和第四步)

模板模式類圖以下:

document_image_rId22.png

類圖說明:

1:是一個抽象類(如:hotDrink)

2:有個模板方法。這個模板方法是final的(如:prepareRecipe方法)

3:由三種方法:

AbsOperation:抽象的方法(泡咖啡、加牛奶)

concreteOp:具體的方法(如燒水。能夠是final的也能夠不是)

hook:鉤子。能夠選的子類能夠覆蓋父類的方法。

咱們來演示下帶有hook的。

好比,如今有了新需求,客戶能夠本身選擇需不須要添加調料。這個怎麼作呢?

本文來源:

凱哥Java(kaigejava)

凱哥我的博客:www.kaigejava.com


咱們重新定義模板:

document_image_rId23.png

tea實現了該模板類,而且不加檸檬的:

document_image_rId24.png

測試運行:

document_image_rId25.png

結果:

document_image_rId26.png

相關文章
相關標籤/搜索