模板方法模式

(一)需求場景

現實生活中,我們會遇到很多時候一些具有特定步驟和流程的事項,比如紙張打印:準備紙張,操作機器,開始打印,結束打印;又或者是製作豆漿牛奶:選材,添加配料,放到豆漿機攪拌;燒菜:準備食材,開火,烹飪,關火等等,這樣的案例數不勝數.它們都有着一定的共性,即使有着相近的步驟,但是由於初始條件和參數等不同,就可以產生不同的結果,食材的不同,烹飪方法的不同都會做出不同的菜品.

(二)基本介紹

模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern.它就是根據這些特性總結出的一種模式,一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行。這種類型的設計模式屬於行爲型模式。

(三)工作原理

1:通過抽象父類模板方法定義總體流程和算法骨架,而由具體的子類去完成各自細節部分的不同實現.
2:AbstractClass 抽象類, 類中實現了模板方法(template),定義了算法的骨架,具體子類需要去實現
3:ConcreteClass 實現各個抽象方法 以完成算法中特點子類的步驟
4:這種設計模式由模板方法完成具體算法設計和架構,子類只負責步驟實現,如果需要進行改動,只要改動模板方法即可
5:模板模式中模板方法一般由final修飾,避免在子類中進行改動
6:模板模式在使用過程中,實例是保存在父類中,即返回類型爲父類,這樣的好處在於即使沒有用instanceof指定子類的種類,程序也能夠正常工作.無論父類類型中的變量保存的是那個子類的實例,程序都可以正常工作,這種原則稱爲裏式替換原則(LSP)

(四)代碼實例

本次實例模擬爲做菜的模板流程,AbstractCooking 定義了燒菜的幾個步驟,然後設定模板方法cooking定義做菜的算法框架,由子類實現,完成各自不同的菜品燒製
在這裏插入圖片描述


/**
 * 模板抽象類
 * 模板方法算法:打開開關,烹飪,關閉電源開關
 **/
public abstract class AbstractCooking {

    final void cooking() {
        //在父類中定義算法結構骨架
        open();
        mixFood();
        close();

    }

    //開啓電源
    abstract void open();

    //混合攪拌
    abstract void mixFood();

    //關閉電源
    abstract void close();
}
public class BraisedFish extends AbstractCooking {
    @Override
    void open() {
        System.out.println("開啓電源");
    }

    @Override
    void mixFood() {
        System.out.println("正在烹飪紅燒魚...");
    }

    @Override
    void close() {
        System.out.println("關閉電源");
    }
}
public class EggSoup extends AbstractCooking {
    @Override
    void open() {
        System.out.println("開啓電源");
    }

    @Override
    void mixFood() {
        System.out.println("正在煮雞蛋湯...");
    }

    @Override
    void close() {
        System.out.println("關閉電源");
    }
}

public class Main {

    public static void main(String[] args) {
        AbstractCooking braisedFish = new BraisedFish();
        braisedFish.cooking();
        AbstractCooking eggSoup = new EggSoup();
        eggSoup.cooking();

    }

}

在這裏插入圖片描述

(五)應用實例

1:spring 中對 Hibernate 的支持,將一些已經定好的方法封裝起來,比如開啓事務、獲取 Session、關閉 Session 等,程序員不重複寫那些已經規範好的代碼,直接丟一個實體就可以保存

2:java.io.InputStream, java.io.OutputStream, java.io.Reader 以及 java.io.Writer 中所有非抽象方法 . 這幾個類都是抽象類,而且有不同類型流的子類實現,但是其中的幾個非抽象方法,例如:InputStream.read()和OutputStream.write()都使用了模板方法模式,不需要子類去實現具體算法邏輯,父類提供算法骨架設計.

3:Spring IOC容器初始化時運用到的模板方法模式
在閱讀Spring源碼的時候,我們肯定會看到這一個方法refresh(),該方法是完成IOC初始化的主要功能實現,包括循環依賴,Bean解析和定義等等.該方法就是一種模板方法實現.其中在ConfigurableApplicationContext 接口中定義該方法

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
	void refresh() throws BeansException, IllegalStateException;
}

在這裏插入圖片描述
AbstractApplicationContext 抽象類實現了ConfigurableApplicationContext接口,並實現了refresh方法,其中基本上完成了IOC初始化的算法設計和架構,定義了模板方法架構設計.而它的子類不需要在重寫該方法,只需要完成各自實現的步驟即可,總體的流程由父類來完成

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext, DisposableBean {
			@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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