Template模板模式可以這樣理解:一個(gè)抽象類公開(kāi)定義了執(zhí)行它的方法的方式/模板,它的子類可以按需要重寫方法實(shí)現(xiàn)柠衅,但調(diào)用將以抽象類中定義的方式進(jìn)行娩脾。這種類型的設(shè)計(jì)模式屬于行為型模式。
通俗來(lái)說(shuō)傻盟,可以這樣理解: 定義一個(gè)操作中算法的骨架,而將一些步驟延遲到子類中嫂丙,模板方法使得子類可以不改變算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟娘赴。
比如:完成一件事情,有固定的數(shù)個(gè)步驟跟啤,但是每個(gè)步驟根據(jù)對(duì)象的不同诽表,而實(shí)現(xiàn)細(xì)節(jié)不同唉锌;就可以在父類中定義一個(gè)完成該事情的總方法,按照完成事件需要的步驟去調(diào)用其每個(gè)步驟的實(shí)現(xiàn)方法竿奏。每個(gè)步驟的具體實(shí)現(xiàn)袄简,由子類完成。
抽象父類(AbstractClass):實(shí)現(xiàn)了模板方法泛啸,定義了算法的骨架绿语。
具體類(ConcreteClass):實(shí)現(xiàn)抽象類中的抽象方法,即不同的對(duì)象的具體實(shí)現(xiàn)細(xì)節(jié)候址。
我們看如下代碼:
package Paint;
//抽象父類
public abstract class DodishTemplate {
/**
* 具體的整個(gè)過(guò)程
*/
protected void dodish() {
this.preparation();
this.doing();
this.carriedDishes();
}
/**
* 備料
*/
public abstract void preparation();
/**
* 做菜
*/
public abstract void doing();
/**
* 上菜
*/
public abstract void carriedDishes();
}
package Paint;
/**
* 子類:西紅柿炒蛋
*/
public class EggsWithTomato extends DodishTemplate {
@Override
public void preparation() {
System.out.println("洗并切西紅柿汞舱,打雞蛋。");
}
@Override
public void doing() {
System.out.println("雞蛋倒入鍋里宗雇,然后倒入西紅柿一起炒昂芜。");
}
@Override
public void carriedDishes() {
System.out.println("將炒好的西紅寺雞蛋裝入碟子里,端給客人吃赔蒲。");
}
}
package Paint;
/**
* 子類:紅燒肉
*/
public class Bouilli extends DodishTemplate {
@Override
public void preparation() {
System.out.println("切豬肉和土豆泌神。");
}
@Override
public void doing() {
System.out.println("將切好的豬肉倒入鍋中炒一會(huì)然后倒入土豆連炒帶燉。");
}
@Override
public void carriedDishes() {
System.out.println("將做好的紅燒肉盛進(jìn)碗里端給客人吃舞虱。");
}
}
package Paint;
// 測(cè)試
public class TestCooking {
public static void main(String[] args) {
DodishTemplate eggsWithTomato = new EggsWithTomato();
eggsWithTomato.dodish();
System.out.println("-----------------------------");
DodishTemplate bouilli = new Bouilli();
bouilli.dodish();
}
}
// 執(zhí)行結(jié)果如下:
#洗并切西紅柿欢际,打雞蛋。
#雞蛋倒入鍋里矾兜,然后倒入西紅柿一起炒损趋。
#將炒好的西紅寺雞蛋裝入碟子里,端給客人吃椅寺。
#-----------------------------
#切豬肉和土豆浑槽。
#將切好的豬肉倒入鍋中炒一會(huì)然后倒入土豆連炒帶燉。
#將做好的紅燒肉盛進(jìn)碗里端給客人吃返帕。
模板設(shè)計(jì)模式看代碼桐玻,不難理解,在加載配置文件的時(shí)候荆萤,可以有不同的加載方式镊靴,如根據(jù)文件系統(tǒng)目錄加載配置文件(FileSystemXmlApplicationContext),類路徑加載配置文件(ClassPathXmlApplicationContext)链韭,以及根據(jù)項(xiàng)目上下文目錄(XmlWebApplicationContext)加載配置文件偏竟。
這個(gè)在加載的過(guò)程中就使用了模板設(shè)計(jì)模式,模板設(shè)計(jì)模式的意圖:定義一個(gè)操作中的算法骨架敞峭,而將一些步驟延遲到子類中踊谋。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
主要解決:一些方法通用儡陨,卻在每一個(gè)子類都重新寫了這一方法褪子。
何時(shí)使用:有一些通用的方法。
如何解決:將這些通用算法抽象出來(lái)骗村。
關(guān)鍵代碼:在抽象類實(shí)現(xiàn)嫌褪,其他步驟在子類實(shí)現(xiàn)。
優(yōu)點(diǎn):
1胚股、封裝不變部分笼痛,擴(kuò)展可變部分。具體細(xì)節(jié)步驟實(shí)現(xiàn)定義在子類中琅拌,子類定義詳細(xì)處理算法是不會(huì)改變算法整體結(jié)構(gòu)
2缨伊、提取公共代碼,便于維護(hù)进宝。代碼復(fù)用的基本技術(shù)刻坊,在數(shù)據(jù)庫(kù)設(shè)計(jì)中尤為重要。
3党晋、行為由父類控制谭胚,子類實(shí)現(xiàn)。存在一種反向的控制結(jié)構(gòu)未玻,通過(guò)一個(gè)父類調(diào)用其子類的操作灾而,通過(guò)子類對(duì)父類進(jìn)行擴(kuò)展增加新的行為,符合“開(kāi)閉原則”扳剿。
缺點(diǎn):每一個(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類來(lái)實(shí)現(xiàn)旁趟,導(dǎo)致類的個(gè)數(shù)增加,使得系統(tǒng)更加龐大庇绽。
使用場(chǎng)景: 1锡搜、有多個(gè)子類共有的方法,且邏輯相同瞧掺。 2余爆、重要的、復(fù)雜的方法夸盟,可以考慮作為模板方法蛾方。
注意事項(xiàng):為防止惡意操作,一般模板方法都加上 final 關(guān)鍵詞上陕。
更多設(shè)計(jì)模式桩砰,我們可以到該網(wǎng)站學(xué)習(xí):
http://www.runoob.com/design-pattern/template-pattern.html