設計模式解密(4)- 模板方法模式
1、簡介
定義:一個操作中算法的框架,而將一些步驟延遲到子類中,使得子類可以不改變算法的結構即可重定義該算法中的某些特定步驟。
模板方法模式,一般是為了統一子類的算法實現步驟,所使用的一種手段或者說是方式。它在父類中定義一系列算法的步驟,而將具體的實現都推遲到子類。
最典型的形式就是一個接口,一個抽象父類,父類中會有一系列的抽象方法,而在子類中去實現這些方法。
類型:行為類模式
2、實例引入
背景:學校老師布置作業,老師布置作業,學生寫作業,老師檢查作業
定義一個抽象作業類
package com.designpattern.templete; /** * 類說明 :學校教師作業 */ public abstract class Homeork { final void workflow(){ //老師布置作業 this.assginHomework(); //學生 做 作業 this.doHomework(); //老師檢查作業 this.checkHomework(); } //布置作業 void assginHomework(){ System.out.println("回家做課後習題,明天檢查!"); } //學生 做 作業 abstract void doHomework(); //檢查作業 void checkHomework(){ System.out.println("檢查作業!"); } }
A同學完成寫作業部分(只關心寫作業的部分)
package com.designpattern.templete; /** * 類說明 :A同學完成作業類 */ public class StudentA extends Homeork{ @Override void doHomework() { //TODO 業務 System.out.println("A同學是這樣完成作業的!"); } }
B同學完成寫作業部分(只關心寫作業的部分)
package com.designpattern.templete; /** * 類說明 :B同學完成作業類 */ public class StudentB extends Homeork{ @Override void doHomework() { // TODO 業務 System.out.println("B同學是這樣完成作業的!"); } }
測試 A、B同學完成作業的過程
package com.designpattern.templete; /** * 類說明 :測試 */ public class Test { public static void main(String[] args) { //測試一次完成作業: 同學都是怎麽樣完成作業的 StudentA A = new StudentA(); A.workflow(); System.out.println("---------------------"); StudentB B = new StudentB(); B.workflow(); } }
結果
回家做課後習題,明天檢查! A同學是這樣完成作業的! 檢查作業! --------------------- 回家做課後習題,明天檢查! B同學是這樣完成作業的! 檢查作業!
3、解決的問題
上面的例子: 學校作業的流程都是一樣的,只是學生做作業是五花八門的 ,所以把確定的部分提取到抽象父類中,可變的部分有子類完成;
學生不需要操作怎麽布置作業,怎麽檢查作業,只需要把自己的任務 --- 寫作業, 完成就行了。
4、應用場景
在多個子類擁有相同的方法,並且這些方法邏輯相同時,可以考慮使用模版方法模式。在程序的主框架相同,細節不同的場合下,也比較適合使用這種模式。
引用:大部分剛步入職場的畢業生應該都有類似的經歷。一個復雜的任務,由公司中的牛人們將主要的邏輯寫好,然後把那些看上去比較簡單的方法寫成抽象的,交給其他的同事去開發。這種分工方式在編程人員水平層次比較明顯的公司中經常用到。比如一個項目組,有架構師,高級工程師,初級工程師,則一般由架構師使用大量的接口、抽象類將整個系統的邏輯串起來,實現的編碼則根據難度的不同分別交給高級工程師和初級工程師來完成。怎麽樣,是不是用到過模版方法模式?
5、優缺點
優點:
容易擴展:一般來說,抽象類中的模版方法是不易反生改變的部分,而抽象方法是容易反生變化的部分,因此通過增加實現類一般可以很容易實現功能的擴展,符合開閉原則。
便於維護:對於模版方法模式來說,正是由於他們的主要邏輯相同,才使用了模版方法,假如不使用模版方法,任由這些相同的代碼散亂的分布在不同的類中,維護起來是非常不方便的。
缺點:
子類的實現也可以影響父類中主邏輯的運行,在靈活的同時,由於子類影響到了父類,違反了裏氏替換原則,也會給程序帶來風險。這就對抽象類的設計有了更高的要求。
6、總結
一次性實現一個算法的不變的部分,並將可變的行為留給子類來實現;
各子類中公共的行為應被提取出來並集中到一個公共父類中以避免代碼重復;
控制子類的擴展;
在多個子類擁有相同的方法,並且這些方法邏輯相同時,可以考慮使用模版方法模式。在程序的主框架相同,細節不同的場合下,也比較適合使用這種模式。
PS:源碼地址 https://github.com/JsonShare/DesignPattern/tree/master
設計模式解密(4)- 模板方法模式