Java設計模式:模闆方法模式

作者:網絡 | 發布時間:2020年10月30日 | 閱讀:892

定義:定義一(yī)個操作中(zhōng)算法的框架,而将一(yī)些步驟延遲到子類中(zhōng),使得子類可以不改變算法的結構即可重定義該算法中(zhōng)的某些特定步驟。

類型:行爲類模式

類圖:

template-method-pattern

事實上,模版方法是編程中(zhōng)一(yī)個經常用到的模式。先來看一(yī)個例子,某日,程序員(yuán)A拿到一(yī)個任務:給定一(yī)個整數數組,把數組中(zhōng)的數由小(xiǎo)到大(dà)排序,然後把排序之後的結果打印出來。經過分(fēn)析之後,這個任務大(dà)體(tǐ)上可分(fēn)爲兩部分(fēn),排序和打印,打印功能好實現,排序就有點麻煩了。但是A有辦法,先把打印功能完成,排序功能另找人做。

    abstract class AbstractSort {

        /**
         * 将數組array由小(xiǎo)到大(dà)排序
         * @param array
         */
        protected abstract void sort(int[] array);

        public void showSortResult(int[] array){
            this.sort(array);
            System.out.print("排序結果:");
            for (int i = 0; i < array.length; i++){
                System.out.printf("%3s", array[i]);
            }
        }
    }

寫完後,A找到剛畢業入職不久的同事B說:有個任務,主要邏輯我(wǒ)已經寫好了,你把剩下(xià)的邏輯實現一(yī)下(xià)吧。于是把AbstractSort類給B,讓B寫實現。B拿過來一(yī)看,太簡單了,10分(fēn)鍾搞定,代碼如下(xià):

class ConcreteSort extends AbstractSort {
    @Override
    protected void sort(int[] array){
        for(int i=0; i&lt;array.length-1; i++){
            selectSort(array, i);
        }
    }

    private void selectSort(int[] array, int index) {
        int MinValue = 32767; // 最小(xiǎo)值變量
        int indexMin = 0; // 最小(xiǎo)值索引變量
        int Temp; // 暫存變量
        for (int i = index; i &lt; array.length; i++) {
            if (array[i] &lt; MinValue){ // 找到最小(xiǎo)值
                MinValue = array[i]; // 儲存最小(xiǎo)值
                indexMin = i; 
            }
        }
        Temp = array[index]; // 交換兩數值
        array[index] = array[indexMin];
        array[indexMin] = Temp;
    }
}

寫好後交給A,A拿來一(yī)運行:

    public class Client {
        public static int[] a = { 10, 32, 1, 9, 5, 7, 12, 0, 4, 3 }; // 預設數據數組
        public static void main(String[] args){
            AbstractSort s = new ConcreteSort();
            s.showSortResult(a);
        }
    }

運行結果:

排序結果: 0 1 3 4 5 7 9 10 12 32

運行正常。行了,任務完成。沒錯,這就是模版方法模式。大(dà)部分(fēn)剛步入職場的畢業生(shēng)應該都有類似B的經曆。一(yī)個複雜(zá)的任務,由公司中(zhōng)的牛人們将主要的邏輯寫好,然後把那些看上去(qù)比較簡單的方法寫成抽象的,交給其他的同事去(qù)開(kāi)發。這種分(fēn)工(gōng)方式在編程人員(yuán)水平層次比較明顯的公司中(zhōng)經常用到。比如一(yī)個項目組,有架構師,高級工(gōng)程師,初級工(gōng)程師,則一(yī)般由架構師使用大(dà)量的接口、抽象類将整個系統的邏輯串起來,實現的編碼則根據難度的不同分(fēn)别交給高級工(gōng)程師和初級工(gōng)程師來完成。怎麽樣,是不是用到過模版方法模式?

模版方法模式的結構

模版方法模式由一(yī)個抽象類和一(yī)個(或一(yī)組)實現類通過繼承結構組成,抽象類中(zhōng)的方法分(fēn)爲三種:

  • 抽象方法:父類中(zhōng)隻聲明但不加以實現,而是定義好規範,然後由它的子類去(qù)實現。

  • 模版方法:由抽象類聲明并加以實現。一(yī)般來說,模版方法調用抽象方法來完成主要的邏輯功能,并且,模版方法大(dà)多會定義爲final類型,指明主要的邏輯功能在子類中(zhōng)不能被重寫。

  • 鈎子方法:由抽象類聲明并加以實現。但是子類可以去(qù)擴展,子類可以通過擴展鈎子方法來影響模版方法的邏輯。

  • 抽象類的任務是搭建邏輯的框架,通常由經驗豐富的人員(yuán)編寫,因爲抽象類的好壞直接決定了程序是否穩定性。

    實現類用來實現細節。抽象類中(zhōng)的模版方法正是通過實現類擴展的方法來完成業務邏輯。隻要實現類中(zhōng)的擴展方法通過了單元測試,在模版方法正确的前提下(xià),整體(tǐ)功能一(yī)般不會出現大(dà)的錯誤。

模版方法的優點及适用場景

容易擴展。一(yī)般來說,抽象類中(zhōng)的模版方法是不易反生(shēng)改變的部分(fēn),而抽象方法是容易反生(shēng)變化的部分(fēn),因此通過增加實現類一(yī)般可以很容易實現功能的擴展,符合開(kāi)閉原則。

便于維護。對于模版方法模式來說,正是由于他們的主要邏輯相同,才使用了模版方法,假如不使用模版方法,任由這些相同的代碼散亂的分(fēn)布在不同的類中(zhōng),維護起來是非常不方便的。

比較靈活。因爲有鈎子方法,因此,子類的實現也可以影響父類中(zhōng)主邏輯的運行。但是,在靈活的同時,由于子類影響到了父類,違反了裏氏替換原則,也會給程序帶來風險。這就對抽象類的設計有了更高的要求。

在多個子類擁有相同的方法,并且這些方法邏輯相同時,可以考慮使用模版方法模式。在程序的主框架相同,細節不同的場合下(xià),也比較适合使用這種模式。


相關内容