閱讀63 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Java中的模板模式

模板模式是一種行為設計模式,它的實現思路是,創建一個樁方法,並且定義一些步驟讓子類來實現。模板方法定義了一個算法的執行步驟,或者說能夠提供一種默認的實現,這種實現概括一部分子類或者全部子類的共同部分。

舉一個例子幫助理解,假設提供一種造房子的算法。算法的步驟就是模擬造房子的過程:建地基、建支撐,最後添加牆和窗戶 – 1. Fundation,2. Pillars,3. Walls,4. Windows。最重要的一點就是不能改變此建造過程,比如不可能在沒用地基的時候就開始建造窗戶。這個例子中,我們就創建了一個模板方法 – 將使用不同的方法完成對房子的建造。

為了確保子類不能重寫(override)這個模板方法,應當使用final

模板方法抽象類

因為設計為一些方法的具體實現留待子類中,所以不得不安排基類為一個抽象類

HouseTemple.java

package com.journaldev.design.template;

public abstract class HouseTemplate {

//template method, final so subclasses can't override
public final void buildHouse(){
buildFoundation();
buildPillars();
buildWalls();
buildWindows();
System.out.println("House is built.");
}

//default implementation
private void buildWindows() {
System.out.println("Building Glass Windows");
}

//methods to be implemented by subclasses
public abstract void buildWalls();
public abstract void buildPillars();

private void buildFoundation() {
System.out.println("Building foundation with cement,iron rods and sand");
}
}

buildHouse()是模板方法並定義了在建造房子過程中一係列方法的執行順序。

WoodenHouse.java

package com.journaldev.design.template;

public class WoodenHouse extends HouseTemplate {

@Override
public void buildWalls() {
System.out.println("Building Wooden Walls");
}

@Override
public void buildPillars() {
System.out.println("Building Pillars with Wood coating");
}
}

此處也應當對其他方法進行重寫,但是為了簡便,此處沒用完成。

GlassHouse.java

package com.journaldev.design.template;</code>

public class GlassHouse extends HouseTemplate {

@Override
public void buildWalls() {
System.out.println("Building Glass Walls");
}

@Override
public void buildPillars() {
System.out.println("Building Pillars with glass coating");
}

}

使用模板方法

用一個測試程序來測試此處已完成的模板方法。

HouseClient.java

package com.journaldev.design.template;

public class HousingClient {

public static void main(String[] args) {

HouseTemplate houseType = new WoodenHouse();

//using template method
houseType.buildHouse();
System.out.println("************");

houseType = new GlassHouse();

houseType.buildHouse();
}

}

注意,client正在調用基類的模板方法並且依賴於不同步驟的實現細節,即這些正在使用的方法,他們一些來著基類另一些來自子類。上述程序的輸出:

Building foundation with cement,iron rods and sand
Building Pillars with Wood coating
Building Wooden Walls
Building Glass Windows
House is built.
************
Building foundation with cement,iron rods and sand
Building Pillars with glass coating
Building Glass Walls
Building Glass Windows
House is built.

 

模板方法的UML圖

JDK中模板方法模式的使用

  • java.io.InputStream, java.io.OutputStream, java.io.Reader 以及 java.io.Writer 中所有非抽象方法。
  • java.util.AbstractList, java.util.AbstractSet 以及 java.util.AbstractMap中所有非抽象方法。

重要提示

  • 模板方法應該是由確定的步驟組成。這些步驟的順序是固定的。基類與子類之間某些方法或者實現可以有所不同。模板方法應該是final的。
  • 大多時候,子類的調用的方法是來自於超類。但是在模板模式中,超類的模板方法調用的方法卻來至於子類,這就是著名的Hollywood原則-“don’t call us, we’ll call you”。
  • 基類方法的默認實現被退化為鉤子Hooks的概念,他們被設計在子類中被重寫,如果你期望一些方法在子類中不被重寫,你可以讓他們為final。比如在例子中buildFoundation()方法是final的,因為不希望它在子類中被重寫。

這就在java中全部的模板方法模式實現,希望你已經喜歡上它了。

最後更新:2017-05-23 12:01:47

  上一篇:go  Java IO: PipedInputStream
  下一篇:go  完美的單例實現(The Perfect Singleton)