模板的原意是指帶有鏤空文字的薄薄的塑料板。只要用筆在模板的鏤空處進(jìn)行臨摹,即使是手寫也能寫出整齊的文字,但是具體寫出的文字是什么感覺則依賴于所用的筆。如果使用簽字筆來臨摹,則可以寫出簽字似的文字;如果使用鉛筆來臨摹,則可以寫出鉛筆字;而如果是用彩色筆臨摹,則可以寫出彩色的字。但是無論使用什么筆,文字的形狀都會(huì)與模板上鏤空處的形狀一致。
10年積累的網(wǎng)站設(shè)計(jì)、做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有寧強(qiáng)免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。本文中所要學(xué)習(xí)的Template Method模式是帶有模板功能的模式,組成模板的方法被定義在父類中。由于這些方法是抽象方法,所以只查看父類的代碼是無法知道這些方法最終會(huì)進(jìn)行何種具體處理的,唯一能知道的就是父類是如何調(diào)用這些方法的。
實(shí)現(xiàn)上述這些抽象方法的是子類。在子類中實(shí)現(xiàn)了抽象方法也就決定了具體的處理。也就是說,只要在不同的子類中實(shí)現(xiàn)不同的具體處理,當(dāng)父類的模板方法被調(diào)用時(shí)程序行為也會(huì)不同。但是,不論子類中的具體實(shí)現(xiàn)如何,處理的流程都會(huì)按照父類中所定義的那樣進(jìn)行。
像這樣在父類中定義處理流程的框架,在子類中實(shí)現(xiàn)具體處理的模式就稱為Template Method模式。
? 用一句話來概括:將具體的處理交給子類。
二、Template Method示例代碼這里的示例程序是一段將字符和字符串循環(huán)顯示5次的簡(jiǎn)單程序。
2.1 各類之間的關(guān)系? 類的功能:
?類圖:
2.2??AbstractDisplay類通過查看AbstractDisplay類的代碼,我們可以知道這3個(gè)方法都是抽象方法。也就是說,如果僅僅查看AbstractDisplay類的代碼,我們無法知道這3個(gè)方法中到底進(jìn)行了什么樣的處理。這是因?yàn)閛pen方法、print方法、close方法的實(shí)際處理被交給了AbstractDisplay類的子類。
? 這里將display用final來修飾,就是表示子類不能重寫display方法。
public abstract class AbstractDisplay {
public abstract void open();
public abstract void print();
public abstract void close();
public final void display() {
open();
for (int i = 0; i< 5; i++) {
print();
}
close();
}
}
2.3?CharDisplay類我們來看看子類之一的charDisplay類。由于CharDisplay類實(shí)現(xiàn)了父類AbstractDisplay類中的3個(gè)抽象方法 open、print、close,因此它并不是抽象類。這樣,當(dāng)dipslay方法被調(diào)用時(shí),比如傳入一個(gè)H,最終顯示出來的會(huì)是:<
public class CharDisplay extends AbstractDisplay{
private char ch;
public CharDisplay(char ch) {
this.ch = ch;
}
@Override
public void open() {
System.out.print("<<");
}
@Override
public void print() {
System.out.print(ch);
}
@Override
public void close() {
System.out.println(">>");
}
}
2.4?StringDisplay類讓我們看看另外一個(gè)子類——StringDisplay類。與CharDisplay類一樣,它也實(shí)現(xiàn)了open、 print、 close方法。
此時(shí),如果dipslay方法被調(diào)用,結(jié)果會(huì)如何呢?假設(shè)我們向charDisplay的構(gòu)造函數(shù)中傳遞的參數(shù)是"Hello,world ,"這個(gè)字符串,那么最終結(jié)果會(huì)像下面這樣:
public class StringDisplay extends AbstractDisplay{
private String string;
private int width;
public StringDisplay(String string) {
this.string = string;
this.width = string.getBytes().length;
}
@Override
public void open() {
printLine();
}
@Override
public void print() {
System.out.println("|" + string + "|");
}
@Override
public void close() {
printLine();
}
private void printLine() {
System.out.print("+");
for (int i = 0; i< width; i++) {
System.out.print("-");
}
System.out.println("+");
}
}
2.5 用于測(cè)試的Main方法? 在該類中生成了CharDisplay類和StringDisplay類的實(shí)例,并調(diào)用了display方法。
public class Main {
public static void main(String[] args) {
AbstractDisplay d1 = new CharDisplay('H');
AbstractDisplay d2 = new StringDisplay("Hello, world.");
AbstractDisplay d3 = new StringDisplay("你好,世界。");
//雖然都調(diào)用的是display方法,但是實(shí)際的程序行為
//取決于CharDisplay和StringDisplay的具體實(shí)現(xiàn)
d1.display();
d2.display();
d3.display();
}
}
2.6 運(yùn)行結(jié)果雖然都調(diào)用的是display方法,但是實(shí)際的程序行為取決于CharDisplay和StringDisplay的具體實(shí)現(xiàn) 。
三、拓展思路的要點(diǎn) 3.1 可以使邏輯處理通用化使用Template Method模式究竟能帶來什么好處呢?這里,它的優(yōu)點(diǎn)是由于在父類的模板方法中編寫了算法,因此無需在每個(gè)子類中再編寫算法。
例如,我們沒使用Template Method模式,而是使用文本編輯器的復(fù)制和粘貼功能編寫了多個(gè)ConcreteClass角色。此時(shí),會(huì)出現(xiàn)ConcreteClass1、ConcreteClass2、Concreteclass3等很多相似的類。編寫完成后立即發(fā)現(xiàn)了Bug還好,但如果是過一段時(shí)間才發(fā)現(xiàn)在Concreteclass1中有Bug,該怎么辦呢?這時(shí),我們就必須將這個(gè)Bug 的修改反映到所有的ConcreteClass角色中才行。
? 而如果是使用Template Method模式進(jìn)行編程,當(dāng)我們?cè)谀0宸椒ㄖ邪l(fā)現(xiàn) Bug時(shí),只需要修改模板方法即可解決問題。
3.2 父類與子類之間的協(xié)作在Template Method模式中,父類和子類是緊密聯(lián)系、共同工作的。因此,在子類中實(shí)現(xiàn)父類中聲明的抽象方法時(shí),必須要理解這些抽象方法被調(diào)用的時(shí)機(jī)。在看不到父類的源代碼的情況下,想要編寫出子類是非常困難的。
3.3 父類與子類的一致性在示例程序中,不論是CharDisplay的實(shí)例還是StringDisplay 的實(shí)例,都是先保存在AbstractDisplay類型的變量中,然后再來調(diào)用display方法的。
使用父類類型的變量保存子類實(shí)例的優(yōu)點(diǎn)是,即使沒有用instanceof等指定子類的種類,程序也能正常工作。
無論在父類類型的變量中保存哪個(gè)子類的實(shí)例,程序都可以正常工作,這種原則稱為里氏替換原則(The Liskov Substitution Principle,LSP )。當(dāng)然,LSP并非僅限于Template Method模式,它是通用的繼承原則。
四、相關(guān)的設(shè)計(jì)模式 4.1 Factory Method模式Factory Method模式是將Template Method模式用于生成實(shí)例的一個(gè)典型例子。
設(shè)計(jì)模式學(xué)習(xí)(七):Factory Method工廠模式_玉面大蛟龍的博客-博客
4.2 Strategy模式在Template Method模式中,可以使用繼承改變程序的行為。這是因?yàn)門emplate Method模式在父類中定義程序行為的框架,在子類中決定具體的處理。
與此相對(duì)的是Strategy模式,它可以使用委托改變程序的行為。與Template Method模式中改變部分程序行為不同的是,Strategy模式用于替換整個(gè)算法。
設(shè)計(jì)模式學(xué)習(xí)(四):Strategy策略模式_玉面大蛟龍的博客-博客
五、思考題?題目:
Java中的接口與抽象類很相似。接口同樣也是抽象方法的集合,但是在TemplateMethod模式中,我們卻無法使用接口來扮演AbstractClass角色,請(qǐng)問這是為什么呢?
答案:
這是因?yàn)門emplateMethod模式中的AbstractClass角色必須實(shí)現(xiàn)處理的流程。在抽象類中可以實(shí)現(xiàn)一部分方法(例如AbstractDisplay類中的display方法),但是在接口中是無法實(shí)現(xiàn)方法的。因此,在TemplateMethod模式中,無法用接口替代抽象類。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧