設計模式(十四)——模板模式(SpringIOC原始碼分析)
1 豆漿製作問題
編寫製作豆漿的程式,說明如下:
1) 製作豆漿的流程 選材--->新增配料--->浸泡--->放到豆漿機打碎
2) 通過新增不同的配料,可以製作出不同口味的豆漿
3) 選材、浸泡和放到豆漿機打碎這幾個步驟對於製作每種口味的豆漿都是一樣的
4) 請使用 模板方法模式 完成 (說明:因為模板方法模式,比較簡單,很容易就想到這個方案,因此就直接使用, 不再使用傳統的方案來引出模板方法模式 )
2 模板方法模式基本介紹
基本介紹
1) 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),z 在一個抽象類公開定義了執行它的方法的模板。它的子類可以按需要重寫方法實現,但呼叫將以抽象類中定義的方式進行。
2) 簡單說,模板方法模式 定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中,使得子類可以不改變一個演算法的結構,就可以重定義該演算法的某些特定步驟
3) 這種型別的設計模式屬於行為型模式。
3 模板方法模式原理類圖
模板方法模式的原理類圖
- 對原理類圖的說明-即(模板方法模式的角色及職責)
1) AbstractClass 抽象類, 類中實現了模板方法(template),定義了演算法的骨架,具體子類需要去實現 其它的抽象方法 operationr2,3,4
2) ConcreteClass 實現抽象方法 operationr2,3,4, 以完成演算法中特點子類的步驟
4 模板方法模式解決豆漿製作問題
1) 應用例項要求
編寫製作豆漿的程式,說明如下:
製作豆漿的流程 選材--->新增配料--->浸泡--->放到豆漿機打碎通過新增不同的配料,可以製作出不同口味的豆漿
選材、浸泡和放到豆漿機打碎這幾個步驟對於製作每種口味的豆漿都是一樣的(紅豆、花生豆漿。。。)
2) 思路分析和圖解(類圖)
3)程式碼說明
package com.lin.templatemethod; public abstract class SoyaMilk { // 模板方法,final型別,不讓子類重寫 final void make() { select(); addCondiments(); soak(); beak(); } void select() { System.out.println("第一步:選好上乘黃豆。"); } // 新增不同的調料 abstract void addCondiments(); void soak() { System.out.println("第三步:黃豆和配料開始浸泡3小時。"); } void beak() { System.out.println("第四步:黃豆和配料放到豆漿機攪拌。"); } }
package com.lin.templatemethod; public class ReadBeanSoya extends SoyaMilk{ @Override void addCondiments() { System.out.println("第二步:加上上好的紅豆。"); } }
package com.lin.templatemethod; public class PeanutSoya extends SoyaMilk{ @Override void addCondiments() { System.out.println("第二步:加上上好的花生。"); } }
package com.lin.templatemethod; public class Client { public static void main(String[] args) { System.out.println("========紅豆豆漿============"); SoyaMilk readBeanSoya = new ReadBeanSoya(); readBeanSoya.make(); System.out.println("========花生豆漿============"); PeanutSoya peanutSoya = new PeanutSoya(); peanutSoya.make(); } }
5 模板方法模式的鉤子方法
1) 在模板方法模式的父類中,我們可以定義一個方法,它預設不做任何事,子類可以視情況要不要覆蓋它,該方法稱為“鉤子”。
2) 還是用上面做豆漿的例子來講解,比如,我們還希望製作純豆漿,不新增任何的配料,請使用鉤子方法對前面的模板方法進行改造 3)程式碼說明
3)程式碼說明
package com.lin.templatemethod.plus; public abstract class SoyaMilk { // 模板方法,final型別,不讓子類重寫 final void make() { select(); if(ifAddCondiments()) { addCondiments(); } soak(); beak(); } void select() { System.out.println("第一步:選好上乘黃豆。"); } // 新增不同的調料 abstract void addCondiments(); void soak() { System.out.println("第三步:黃豆和配料開始浸泡3小時。"); } void beak() { System.out.println("第四步:黃豆和配料放到豆漿機攪拌。"); } // 鉤子方法 public boolean ifAddCondiments() { return true; } }
package com.lin.templatemethod.plus; public class PureSoyaMilk extends SoyaMilk{ @Override void addCondiments() { // TODO Auto-generated method stub } @Override public boolean ifAddCondiments() { return false; } }
package com.lin.templatemethod.plus; public class Client { public static void main(String[] args) { System.out.println("========紅豆豆漿============"); SoyaMilk readBeanSoya = new ReadBeanSoya(); readBeanSoya.make(); System.out.println("========花生豆漿============"); SoyaMilk peanutSoya = new PeanutSoya(); peanutSoya.make(); System.out.println("========純豆漿============"); SoyaMilk pureSoya = new PureSoyaMilk(); pureSoya.make(); } }
6 模板方法模式在 Spring 框架應用的原始碼分析
1) Spring IOC 容器初始化時運用到的模板方法模式
2) 程式碼分析+角色分析+說明類圖
3) 針對原始碼的類圖(說明層次關係)
7 模板方法模式的注意事項和細節
1) 基本思想是:演算法只存在於一個地方,也就是在父類中,容易修改。需要修改演算法時,只要修改父類的模板方法或者已經實現的某些步驟,子類就會繼承這些修改
2) 實現了最大化程式碼複用。父類的模板方法和已實現的某些步驟會被子類繼承而直接使用。
3) 既統一了演算法,也提供了很大的靈活性。父類的模板方法確保了演算法的結構保持不變,同時由子類提供部分步驟的實現。
4) 該模式的不足之處:每一個不同的實現都需要一個子類實現,導致類的個數增加,使得系統更加龐大
5) 一般模板方法都加上 final 關鍵字, 防止子類重寫模板方法.
6) 模板方法模式使用場景:當要完成在某個過程,該過程要執行一系列步驟 ,這一系列的步驟基本相同,但其個別步驟在實現時 可能不同,通常考慮用模板方法模式來處理
僅供參考,有錯誤還請指出!
有什麼想法,評論區留言,互相指教指