java設計模式02.1Template Method-----組件協作模式(Template Method、Strategy、Observer/Event)

前言

GOF-23模式分類,傳統分爲創建型,結構型,行爲型。

  1. 創建型模式:用於描述“怎樣創建對象”,它的主要特點是“將對象的創建與使用分離”。GoF 中提供了單例、原型、工廠方法、抽象工廠、建造者等 5 種創建型模式。
  2. 結構型模式:用於描述如何將類或對象按某種佈局組成更大的結構,GoF 中提供了代理、適配器、橋接、裝飾、外觀、享元、組合等 7 種結構型模式。
  3. 行爲型模式:用於描述類或對象之間怎樣相互協作共同完成單個對象都無法單獨完成的任務,以及怎樣分配職責。GoF 中提供了模板方法、策略、命令、職責鏈、狀態、觀察者、中介者、迭代器、訪問者、備忘錄、解釋器等 11 種行爲型模式。
    李建忠老師給出了他的分類方式:
    在這裏插入圖片描述
    這樣的分類方式,更加的細緻。我首先要整理的就是組件協作中的Template Method。

Template Method

定義:定義一個操作中的算法骨架(穩定),而將一些步驟延遲(變化)到子類中。TemplateMethod使得子類可以不改變(複用)一個算法的結構也可重定義(override重寫)該算法特定步驟。
該模式的主要優點如下。

  1. 它封裝了不變部分,擴展可變部分。它把認爲是不變部分的算法封裝到父類中實現,而把可變部分算法由子類繼承實現,便於子類繼續擴展。
  2. 它在父類中提取了公共的部分代碼,便於代碼複用。
  3. 部分方法是由子類實現的,因此子類可以通過擴展方式增加相應的功能,符合開閉原則。

該模式的主要缺點如下。

  1. 對每個不同的實現都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象。
  2. 父類中的抽象方法由子類實現,子類執行的結果會影響父類的結果,這導致一種反向的控制結構,它提高了代碼閱讀的難度。
    一些方法通用,卻在每一個子類都重新寫了這一方法。比如後面的試卷,每個學生都要用,不如進行進行抽離出來,形成一個模版。
    附加:這裏的延遲涉及一個在之前所說的重構關鍵技法中的晚綁定,就是一種“你別來調用我,我來調用你”。這個“早晚”,就是調用的代碼出現早晚。兩種選擇,你寫完整個流程,去調用別人已經寫好的接口(這個代碼在你之前就有了),就是早綁定。第二種,別人有整個流程,規定什麼操作可以重構,你再去重構對應的操作,讓他來調用你寫好的代碼,被調用的代碼(你的代碼)是在原代碼之後纔出現的就是一個晚綁定。就是被調用代碼的出現時間。

模版結構

在這裏插入圖片描述

使用步驟

  1. 創建抽象類,列出算法骨架。以參考文獻二中案例爲例。
package com.lwx.template_method;

/**
 * Created with IntelliJ IDEA.
 * Description: 考題試卷
 * User: lwx
 * Date: 2019-03-11
 * Time: 22:39
 */
public abstract class TestPaper {

    private void testQuestion1(){
        System.out.println("楊過得到,後來給了郭靖,煉成倚天劍、屠龍刀的玄鐵可能是:A.球磨鑄鐵 B.馬口鐵 C.高速合金鋼 D。碳素纖維");
        System.out.println("學生答案:" + answer1());
    }

    private void testQuestion2(){
        System.out.println("楊過、程英、陸無雙剷除了情花造成:A.使這種植物不再害人 B.使一種珍稀物種滅絕 C.破壞了那個生物圈的生態平衡 D.造成該地區沙漠化");
        System.out.println("學生答案:" + answer2());
    }

    private void testQuestion3(){
        System.out.println("藍鳳凰致使華山師徒、核谷六仙嘔吐不止,如果你是大夫,會給他們開什麼藥:A.阿匹斯林 B.牛黃解毒片 " +
                "C.氟哌酸 D.讓他們喝大量的生牛奶 E.以上全不對");
        System.out.println("學生答案:" + answer3());
    }

    public void answerQuestion() {
        testQuestion1();
        testQuestion2();
        testQuestion3();
    }

    abstract String answer1();

    abstract String answer2();

    abstract String answer3();
}
  1. 實現骨架中的抽象方法。這裏是學生A與學生B 對試卷進行作答
package com.lwx.template_method;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lwx
 * Date: 2019-03-11
 * Time: 22:49
 */
public class StudentAPaper extends TestPaper {

    @Override
    String answer1() {
        return "B";
    }

    @Override
    String answer2() {
        return "A";
    }

    @Override
    String answer3() {
        return "C";
    }
}
package com.lwx.template_method;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lwx
 * Date: 2019-03-11
 * Time: 22:49
 */
public class StudentBPaper extends TestPaper {
    @Override
    String answer1() {
        return "C";
    }

    @Override
    String answer2() {
        return "B";
    }

    @Override
    String answer3() {
        return "A";
    }
}
  1. 模版結構中的客戶類,也就是主方法。
package com.lwx.template_method;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lwx
 * Date: 2019-03-11
 * Time: 22:00
 */
public class Test {

    public static void main(String[] args) {
        TestPaper testPaper = null;

        System.out.println("學生A答題");
        testPaper = new StudentAPaper();
        testPaper.answerQuestion();

        System.out.println("----------------------------");

        System.out.println("學生B答題");
        testPaper = new StudentBPaper();
        testPaper.answerQuestion();
    }

}
  1. 運行效果
    在這裏插入圖片描述
    由於試卷是一樣的,所以完全可以抽象成父類,然後在子類中去填寫答案,這樣就是通過把不變的行爲搬移到超類,去除子類中的重複代碼,這也是模板方法的特點。

用設計模式就是要看見代碼中的變與不變,極大可能的實現複用。

模版方法:某個流程是固定的,只存在中間某步的具體操作的細微差別。比如說:去銀行辦理業務一般要經過以下4個流程:取號、排隊、辦理具體業務、對銀行工作人員進行評分等,其中取號、排隊和對銀行工作人員進行評分的業務對每個客戶是一樣的,可以在父類中實現,但是辦理具體業務卻因人而異,它可能是存款、取款或者轉賬等,可以延遲到子類中實現。

參考文獻

[1]http://c.biancheng.net/view/1376.html
[2]https://www.cnblogs.com/yijinqincai/p/10513843.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章