一、什么是模板方法模式
創(chuàng)新互聯(lián)建站服務(wù)項目包括呼倫貝爾網(wǎng)站建設(shè)、呼倫貝爾網(wǎng)站制作、呼倫貝爾網(wǎng)頁制作以及呼倫貝爾網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,呼倫貝爾網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到呼倫貝爾省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
概念:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
通俗的講,模板方法模式是通過把不變行為搬到超類,去除子類里面的重復(fù)代碼提現(xiàn)它的優(yōu)勢,它提供了一個很好的代碼復(fù)用平臺。當不可變和可變的方法在子類中混合在一起的時候,不變的方法就會在子類中多次出現(xiàn),這樣如果摸個方法需要修改則需要修改很多個,雖然這個這個問題在設(shè)計之初就應(yīng)該想好。這個時候模板方法模式就起到了作用了,通過模板方法模式把這些重復(fù)出現(xiàn)的方法搬到單一的地方,這樣就可以幫助子類擺脫重復(fù)不變的糾纏。
舉個好懂的例子,小時候筆者家里窮,在農(nóng)村上小學(xué)的時候考試都是每個學(xué)生手抄試卷,因為那個時候?qū)W校還沒有試卷印刷。全班五十多個學(xué)生每個學(xué)生都要重復(fù)抄一遍黑板的試卷,并且像筆者這樣的近視眼很容易就抄錯了,8抄成3,7抄成1等到,然后明明做對了但是分數(shù)就是不高,導(dǎo)致筆者一直是全班倒數(shù)。這就是個很嚴重的重復(fù)不可變的問題,現(xiàn)在條件好了不少,學(xué)生不需要抄試卷,試卷印刷就解決了這個重復(fù)抄試卷的問題。模板方法也是類似。
二、模式對比
1、抄試卷模式
筆者就以抄試卷模式為名來闡述重復(fù)不變帶來的不便,下面會對該模式進行改進。
學(xué)生甲抄的試卷
public class TestPaperA { //試卷第一題 public void testQuestion1(){ System.out.println("小龍女是楊過的什么親戚?() A.小姨媽 B.大姨媽 C.姑媽 D.舅媽"); System.out.println("答案:C"); } //試卷第二題 public void testQuestion2(){ System.out.println("全真教的首任掌門是誰?A.周伯通 B.歐陽鋒 C.王重陽 D.西門吹牛"); System.out.println("答案:C"); } //試卷第三題 public void testQuestion3(){ System.out.println("《天龍八部》中被封為南院大王的大俠是誰?A.段譽 B.喬峰 C.慕容復(fù) D.段智興"); System.out.println("答案:B"); } }
學(xué)生乙抄的試卷
public class TestPaperB { //試卷第一題 public void testQuestion1(){ System.out.println("小龍女是楊過的什么親戚?() A.小姨媽 B.大姨媽 C.姑媽 D.舅媽"); System.out.println("答案:A"); } //試卷第二題 public void testQuestion2(){ System.out.println("全真教的首任掌門是誰?A.周伯通 B.歐陽鋒 C.王重陽 D.西門吹牛"); System.out.println("答案:C"); } //試卷第三題 public void testQuestion3(){ System.out.println("《天龍八部》中被封為南院大王的大俠是誰?A.段譽 B.喬峰 C.慕容復(fù) D.段智興"); System.out.println("答案:D"); } }
客戶端代碼
public class ShowAnswer { public static void main(String[] args) { System.out.println("學(xué)生甲的試卷"); TestPaperA stuA = new TestPaperA(); stuA.testQuestion1(); stuA.testQuestion2(); stuA.testQuestion3(); System.out.println("學(xué)生乙的試卷"); TestPaperB stuB = new TestPaperB(); stuB.testQuestion1(); stuB.testQuestion2(); stuB.testQuestion3(); } }
很容易發(fā)現(xiàn)上面兩個學(xué)生抄的試卷有很多重復(fù)的地方,比如試卷的題目,輸出答案的方法,這些都在每個學(xué)生試卷類中混合在一起了,既不利于維護,也不利于瀏覽,下面看一下模板方法模式是怎么改進的。
2、模板方法模式
將每個學(xué)生試卷的重復(fù)部分提取出來,題目,作答等等。
首先改造試卷類,將該類改為抽象類,在該類中我添加了三個抽象的方法用于子類實現(xiàn),學(xué)生都是要作答的,但是答案不一樣,所以可以將作答的過程作為重復(fù)不變的方法提取出來,代碼如下。
public abstract class TestPaper { //試卷第一題 public void testQuestion1(){ System.out.println("小龍女是楊過的什么親戚?() A.小姨媽 B.大姨媽 C.姑媽 D.舅媽"); System.out.println("答案:" + answer1()); } //試卷第二題 public void testQuestion2(){ System.out.println("全真教的首任掌門是誰?A.周伯通 B.歐陽鋒 C.王重陽 D.西門吹牛"); System.out.println("答案:" + answer2()); } //試卷第三題 public void testQuestion3(){ System.out.println("《天龍八部》中被封為南院大王的大俠是誰?A.段譽 B.喬峰 C.慕容復(fù) D.段智興"); System.out.println("答案:" + answer3()); } //這三個鉤子方法是給每個子類去實現(xiàn),并返回答案的 public abstract String answer1(); public abstract String answer2(); public abstract String answer3(); //模板方法,考試的過程,定義基本的考試過程,子類回調(diào) public void exam(){ testQuestion1(); testQuestion2(); testQuestion3(); } }
首先來看第一個學(xué)生的考試情況
public class TestPaperA extends TestPaper{ @Override public String answer1() { return "A"; } @Override public String answer2() { return "B"; } @Override public String answer3() { return "D"; } }
其他學(xué)生的試卷可能答案不是一樣的,但是基本的答題過程就是一樣的,所以就不重復(fù)寫了,下面看下客戶端代碼。
public class ShowAnswer { public static void main(String[] args) { TestPaper testPaper = new TestPaperA(); testPaper.exam(); } }
可以看待客戶端代碼也減輕了很多,這樣邏輯清晰,利于維護,優(yōu)勢很明顯,下面看下具體答題情況。
小龍女是楊過的什么親戚?() A.小姨媽 B.大姨媽 C.姑媽 D.舅媽
答案:A
全真教的首任掌門是誰?A.周伯通 B.歐陽鋒 C.王重陽 D.西門吹牛
答案:B
《天龍八部》中被封為南院大王的大俠是誰?A.段譽 B.喬峰 C.慕容復(fù) D.段智興
答案:D
3、模板方法模式的基本結(jié)構(gòu)
AbstractClass是一個抽象類,其實就是一個抽象模板,定義并實現(xiàn)了一個模板方法。這個模板方法一般是一個具體的實現(xiàn),他給出了一些邏輯的骨架,而邏輯的組成在相應(yīng)的抽象類中,推遲到了子類實現(xiàn)。代碼如下
public abstract class AbstractClass { //一些抽象行為,可以理解為重復(fù)不變的方法,提取到抽象類 public abstract void primitiveOperation1(); public abstract void primitiveOperation2(); //模板方法,給出了具體邏輯的骨架,而邏輯的組成是一些相應(yīng)的抽象操作,他們都推遲到子類實現(xiàn) public void templateMothed(){ primitiveOperation1(); primitiveOperation2(); } }
ConcreteClass,實現(xiàn)父類所定義的一個或多個抽象方法。每一個AbstractClass都可以有一個或者多個ConcreteClass與之對應(yīng),而每一個ConcreteClass都可以給出這些抽象方法(也就是骨架的組成步驟)的不同實現(xiàn),從而得到的實現(xiàn)都不同。
public class ConcreteClassA extends AbstractClass{ @Override public void primitiveOperation1() { System.out.println("子類A的操作1"); } @Override public void primitiveOperation2() { System.out.println("子類A的操作2"); } }
public class ConcreteClassB extends AbstractClass{ @Override public void primitiveOperation1() { System.out.println("子類B的操作1"); } @Override public void primitiveOperation2() { System.out.println("子類B的操作2"); } }
上面定義了兩個具體的實現(xiàn),更多的實現(xiàn)其實都是一致的,這里就不多多說了。下面看下客戶端代碼
public class Show { public static void main(String[] args) { AbstractClass c; c = new ConcreteClassA(); c.templateMothed(); c = new ConcreteClassB(); c.templateMothed(); } }
輸入如下
子類A的操作1
子類A的操作2
子類B的操作1
子類B的操作2
4、UML圖
三、總結(jié)
模板方法模式就是為了將重復(fù)不變的代碼提取到一個抽象類中。當我們要完成在某一細節(jié)層次一致的一個過程或一系列步驟,但其個別步驟在更詳細的層次上的實現(xiàn)可能不同時,我們通??紤]用模板方法模式來處理。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。