設(shè)計(jì)模式之模版方法模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
定義:定義一個(gè)操作中算法的框架,而將一些步驟延遲到子類(lèi)中,使得子類(lèi)可以不改變算法的結(jié)構(gòu)即可重定義該算法中的某些特定步驟。
類(lèi)型:行為類(lèi)模式
類(lèi)圖:

事實(shí)上,模版方法是編程中一個(gè)經(jīng)常用到的模式。先來(lái)看一個(gè)例子,某日,程序員A拿到一個(gè)任務(wù):給定一個(gè)整數(shù)數(shù)組,把數(shù)組中的數(shù)由小到大排序,然后把排序之后的結(jié)果打印出來(lái)。經(jīng)過(guò)分析之后,這個(gè)任務(wù)大體上可分為兩部分,排序和打印,打印功能好實(shí)現(xiàn),排序就有點(diǎn)麻煩了。但是A有辦法,先把打印功能完成,排序功能另找人做。
abstract class AbstractSort {
/**
* 將數(shù)組array由小到大排序
* @param array
*/
protected abstract void sort(int[] array);
public void showSortResult(int[] array){
this.sort(array);
System.out.print("排序結(jié)果:");
for (int i = 0; i < array.length; i++){
System.out.printf("%3s", array[i]);
}
}
}
寫(xiě)完后,A找到剛畢業(yè)入職不久的同事B說(shuō):有個(gè)任務(wù),主要邏輯我已經(jīng)寫(xiě)好了,你把剩下的邏輯實(shí)現(xiàn)一下吧。于是把AbstractSort類(lèi)給B,讓B寫(xiě)實(shí)現(xiàn)。B拿過(guò)來(lái)一看,太簡(jiǎn)單了,10分鐘搞定,代碼如下:
class ConcreteSort extends AbstractSort {
@Override
protected void sort(int[] array){
for(int i=0; i<array.length-1; i++){
selectSort(array, i);
}
}
private void selectSort(int[] array, int index) {
int MinValue = 32767; // 最小值變量
int indexMin = 0; // 最小值索引變量
int Temp; // 暫存變量
for (int i = index; i < array.length; i++) {
if (array[i] < MinValue){ // 找到最小值
MinValue = array[i]; // 儲(chǔ)存最小值
indexMin = i;
}
}
Temp = array[index]; // 交換兩數(shù)值
array[index] = array[indexMin];
array[indexMin] = Temp;
}
}
寫(xiě)好后交給A,A拿來(lái)一運(yùn)行:
public class Client {
public static int[] a = { 10, 32, 1, 9, 5, 7, 12, 0, 4, 3 }; // 預(yù)設(shè)數(shù)據(jù)數(shù)組
public static void main(String[] args){
AbstractSort s = new ConcreteSort();
sshowSortResult(a);
}
}
運(yùn)行結(jié)果:
排序結(jié)果: 0 1 3 4 5 7 9 10 12 32
運(yùn)行正常。行了,任務(wù)完成。沒(méi)錯(cuò),這就是模版方法模式。大部分剛步入職場(chǎng)的畢業(yè)生應(yīng)該都有類(lèi)似B的經(jīng)歷。一個(gè)復(fù)雜的任務(wù),由公司中的牛人們將主要的邏輯寫(xiě)好,然后把那些看上去比較簡(jiǎn)單的方法寫(xiě)成抽象的,交給其他的同事去開(kāi)發(fā)。這種分工方式在編程人員水平層次比較明顯的公司中經(jīng)常用到。比如一個(gè)項(xiàng)目組,有架構(gòu)師,高級(jí)工程師,初級(jí)工程師,則一般由架構(gòu)師使用大量的接口、抽象類(lèi)將整個(gè)系統(tǒng)的邏輯串起來(lái),實(shí)現(xiàn)的編碼則根據(jù)難度的不同分別交給高級(jí)工程師和初級(jí)工程師來(lái)完成。怎么樣,是不是用到過(guò)模版方法模式?
模版方法模式的結(jié)構(gòu)
模版方法模式由一個(gè)抽象類(lèi)和一個(gè)(或一組)實(shí)現(xiàn)類(lèi)通過(guò)繼承結(jié)構(gòu)組成,抽象類(lèi)中的方法分為三種:
- 抽象方法:父類(lèi)中只聲明但不加以實(shí)現(xiàn),而是定義好規(guī)范,然后由它的子類(lèi)去實(shí)現(xiàn)。
- 模版方法:由抽象類(lèi)聲明并加以實(shí)現(xiàn)。一般來(lái)說(shuō),模版方法調(diào)用抽象方法來(lái)完成主要的邏輯功能,并且,模版方法大多會(huì)定義為final類(lèi)型,指明主要的邏輯功能在子類(lèi)中不能被重寫(xiě)。
- 鉤子方法:由抽象類(lèi)聲明并加以實(shí)現(xiàn)。但是子類(lèi)可以去擴(kuò)展,子類(lèi)可以通過(guò)擴(kuò)展鉤子方法來(lái)影響模版方法的邏輯。
- 抽象類(lèi)的任務(wù)是搭建邏輯的框架,通常由經(jīng)驗(yàn)豐富的人員編寫(xiě),因?yàn)槌橄箢?lèi)的好壞直接決定了程序是否穩(wěn)定性。
實(shí)現(xiàn)類(lèi)用來(lái)實(shí)現(xiàn)細(xì)節(jié)。抽象類(lèi)中的模版方法正是通過(guò)實(shí)現(xiàn)類(lèi)擴(kuò)展的方法來(lái)完成業(yè)務(wù)邏輯。只要實(shí)現(xiàn)類(lèi)中的擴(kuò)展方法通過(guò)了單元測(cè)試,在模版方法正確的前提下,整體功能一般不會(huì)出現(xiàn)大的錯(cuò)誤。
模版方法的優(yōu)點(diǎn)及適用場(chǎng)景
容易擴(kuò)展。一般來(lái)說(shuō),抽象類(lèi)中的模版方法是不易反生改變的部分,而抽象方法是容易反生變化的部分,因此通過(guò)增加實(shí)現(xiàn)類(lèi)一般可以很容易實(shí)現(xiàn)功能的擴(kuò)展,符合開(kāi)閉原則。
便于維護(hù)。對(duì)于模版方法模式來(lái)說(shuō),正是由于他們的主要邏輯相同,才使用了模版方法,假如不使用模版方法,任由這些相同的代碼散亂的分布在不同的類(lèi)中,維護(hù)起來(lái)是非常不方便的。
比較靈活。因?yàn)橛秀^子方法,因此,子類(lèi)的實(shí)現(xiàn)也可以影響父類(lèi)中主邏輯的運(yùn)行。但是,在靈活的同時(shí),由于子類(lèi)影響到了父類(lèi),違反了里氏替換原則,也會(huì)給程序帶來(lái)風(fēng)險(xiǎn)。這就對(duì)抽象類(lèi)的設(shè)計(jì)有了更高的要求。
在多個(gè)子類(lèi)擁有相同的方法,并且這些方法邏輯相同時(shí),可以考慮使用模版方法模式。在程序的主框架相同,細(xì)節(jié)不同的場(chǎng)合下,也比較適合使用這種模式。
相關(guān)文章
java有界類(lèi)型參數(shù)的實(shí)例用法
小編給大家整理了一篇關(guān)于java有界類(lèi)型參數(shù)的使用的相關(guān)文章及擴(kuò)展實(shí)例內(nèi)容,有需要的朋友們可以學(xué)習(xí)參考下。2021-07-07
解決springboot整合cxf-jaxrs中json轉(zhuǎn)換的問(wèn)題
這篇文章主要介紹了解決springboot整合cxf-jaxrs中json轉(zhuǎn)換的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-09-09
springboot項(xiàng)目如何使用切面記錄用戶操作日志
這篇文章主要介紹了springboot項(xiàng)目如何使用切面記錄用戶操作日志,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明
這篇文章主要介紹了反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java用單向環(huán)形鏈表來(lái)解決約瑟夫環(huán)Josepfu問(wèn)題
如果把單鏈表的最后一個(gè)節(jié)點(diǎn)的指針指向鏈表頭部,而不是指向NULL,那么就構(gòu)成了一個(gè)單向循環(huán)鏈表,通俗講就是把尾節(jié)點(diǎn)的下一跳指向頭結(jié)點(diǎn)2021-10-10
java使用EditText控件時(shí)不自動(dòng)彈出輸入法的方法
這篇文章主要介紹了java使用EditText控件時(shí)不自動(dòng)彈出輸入法的方法,需要的朋友可以參考下2015-03-03
Java數(shù)據(jù)結(jié)構(gòu)與算法學(xué)習(xí)之循環(huán)鏈表
循環(huán)鏈表是另一種形式的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。它的特點(diǎn)是表中最后一個(gè)結(jié)點(diǎn)的指針域指向頭結(jié)點(diǎn),整個(gè)鏈表形成一個(gè)環(huán)。本文將為大家詳細(xì)介紹一下循環(huán)鏈表的特點(diǎn)與使用,需要的可以了解一下2021-12-12

