重復(fù)=易錯(cuò)+難改
場(chǎng)景:學(xué)生抄老師寫在黑板上的題目,然后再做答案。
每個(gè)同學(xué)抄的試卷非常類似,除了答案不同,沒什么不一樣,如果每個(gè)同學(xué)抄的試卷是一個(gè)類,這樣寫容易錯(cuò),又難以維護(hù)。如果老師突然要改題目,每個(gè)人都需要改代碼,如果有人抄錯(cuò),更是大問題。
應(yīng)該抽象出一個(gè)父類,讓兩個(gè)子類繼承,公共的試題代碼寫在父類當(dāng)中。
既然用了繼承,并且肯定這個(gè)繼承有意義,就應(yīng)該要成為子類的模板,所有重復(fù)的代碼都應(yīng)該上升到父類去,而不是讓每個(gè)子類都去重復(fù)。
當(dāng)要完成某一細(xì)節(jié)層次一致的一個(gè)過程或一系列步驟,但其個(gè)別步驟在更詳細(xì)的層次上的實(shí)現(xiàn)可能不同時(shí),通??紤]用模板方法模式來處理。
基于上面的場(chǎng)景,可以用以下代碼實(shí)現(xiàn):
父類
public abstract class TestPaper {
public void question1() {
print("試題1");
print("答案:" + answer1());
}
/**
* 答案的方法目的是給繼承的子類重寫
* 因?yàn)檫@里每個(gè)人的答案都是不同的
* @return
*/
protected abstract String answer1();
public void question2() {
print("試題2");
print("答案:" + answer2());
}
protected abstract String answer2();
}
子類A
public class TestPaperA extends TestPaper {
/**
* 重寫父類的方法
* @return
*/
@Override
protected String answer1() {
return "A";
}
@Override
protected String answer2() {
return "B";
}
}
子類B
public class TestPaperB extends TestPaper {
@Override
protected String answer1() {
return "B";
}
@Override
protected String answer2() {
return "C";
}
}
測(cè)試代碼
public class Test {
public static void main(String[] args) {
print("學(xué)生A的試卷");
//將子類變量聲明成父類,利用多態(tài)性,實(shí)現(xiàn)代碼的復(fù)用
TestPaper a = new TestPaperA();
a.question1();
a.question2();
print("學(xué)生B的試卷");
TestPaper b = new TestPaperB();
b.question1();
b.question2();
}
}
模板方法模式
模板方法模式,定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。[DP]
模板方法模式(TemplateMethod)結(jié)構(gòu)圖

AbstractClass是抽象類,其實(shí)也就是一個(gè)抽象模板,定義并實(shí)現(xiàn)了一個(gè)模板方法。這個(gè)模板方法一般是一個(gè)具體方法,它給出了一個(gè)頂級(jí)邏輯的骨架,而邏輯的組成步驟在相應(yīng)的抽象操作中,推遲到子類實(shí)現(xiàn)。頂級(jí)邏輯也有可能調(diào)用一些具體方法。
public abstract class AbstractClass {
/**
* 一些抽象行為,放到子類去實(shí)現(xiàn)
*/
public abstract void primitiveOperation1();
public abstract void primitiveOperation2();
/**
* 模板方法,給出了邏輯的骨架
* 而邏輯的組成是一些相應(yīng)的抽象操作,他們都推遲到子類實(shí)現(xiàn)
*/
public void templateMethod(){
primitiveOperation1();
primitiveOperation2();
}
}
ConcreteClass,實(shí)現(xiàn)父類所定義的一個(gè)或多個(gè)抽象方法。每一個(gè)AbstractClass都可以有任意多個(gè)ConcreteClass與之對(duì)應(yīng),而每一個(gè)ConcreteClass都可以給出這些抽象方法(也就是頂級(jí)邏輯的組成步驟)的不同實(shí)現(xiàn),從而使得頂級(jí)邏輯的實(shí)現(xiàn)各不相同。
public class ConcreteClass extends AbstractClass {
@Override
public void primitiveOperation1() {
print("具體類1方法1的具體實(shí)現(xiàn)");
}
@Override
public void primitiveOperation2() {
print("具體類1方法2的具體實(shí)現(xiàn)");
}
}
測(cè)試代碼
public class Test2 {
public static void main(String[] args) {
AbstractClass c = new ConcreteClass();
c.templateMethod();
}
}
模板方法模式特點(diǎn)
模板方法模式是通過把不變行為搬移到超類,去除子類中的重復(fù)代碼來體現(xiàn)它的優(yōu)勢(shì)。模板方法模式就是提供了一個(gè)很好的代碼復(fù)用平臺(tái)。當(dāng)不變的和可變的行為在方法的子類實(shí)現(xiàn)中混合在一起的時(shí)候,不變的行為就會(huì)在子類中重復(fù)出現(xiàn)。通過模板方法模式把這些行為搬移到單一的地方,就幫助子類擺脫重復(fù)的不變行為的糾纏。