什么是Template Method模式


在父类中定义处理流程的框架,在子类中具体处理的模式就称为 Template Method 模式。

示例程序


类的一览表

名字说明
AbstractDisplay只实现了 display 方法的抽象类
CharDisplay实现了 open、print、close 方法的类
StringDisplay实现了 open、print、close 方法的类
Main测试程序行为的类

类图

AbstractDisplay类

除了 display 方法实现了,其他的都是抽象方法:

public abstract class AbstractDisplay { // 抽象类AbstractDisplay  
    public abstract void open(); // 交给子类去实现的抽象方法 (1) open    public abstract void print(); // 交给子类去实现的抽象方法 (2) print    public abstract void close(); // 交给子类去实现的抽象方法 (3) close    public final void display() {  
        open();  
        for (int i = 0; i < 5; i++) { // 循环调用5次print  
            print();  
        }  
        close();  
    }  
}

CharDisplay类

CharDisplay 实现了父类 AbstractDisplay

实现的方法处理:

方法名处理
open显示字符串“<<”
print显示构造函数接受的 1 个字符
close显示字符串 “>>”

当display被调用时,假如传入的参数是 “H”,那么会输出如下:

<<HHHHH>>

StringDisplay

同上,实现了 AbstractDisplay,其方法处理如下:

方法名处理
open显示字符串“+-------------+”
print在构造函数接受的字符串前轴分别加上“|”并显示
close显示字符串“+-------------+”

输出应该是这样的:

+-------------+
|Hello, World.|
|Hello, World.|
|Hello, World.|
|Hello, World.|
|Hello, World.|
+-------------+
public class StringDisplay extends AbstractDisplay {  
    private final String string;  
    private final int width;  
  
    public StringDisplay(String string) {  
        this.string = string;  
        this.width = string.length();  
    }  
  
    public StringDisplay(String string, int width) {  
        this.string = string;  
        this.width = width;  
    }  
  
    @Override  
    public void open() {  
        printLine();  
    }  
  
    @Override  
    public void print() {  
        System.out.println("|" + string + "|");  
    }  
  
    @Override  
    public void close() {  
        printLine();  
    }  
  
    public void printLine() {  
        System.out.print("+");  
        for (int i = 0; i < width; i++) {  
            System.out.print("-");  
        }  
        System.out.println("+");  
    }  
}

Main类

public class Main {  
    public static void main(String[] args) {  
        AbstractDisplay charDisplay = new CharDisplay('T');  
        charDisplay.display();  
        AbstractDisplay stringDisplay = new StringDisplay("Hello, world!");  
        stringDisplay.display();  
        AbstractDisplay stringDisplay1 = new StringDisplay("你好, 世界!", 10);  
        stringDisplay1.display();  
    }  
}

Template Method模式的登场角色


Template Method 模式中,只有两个登场角色如下:

  • AbstractClass(抽象类)
    • 不仅声明一个实现模板的方法,还要声明在模板方法中使用的抽象方法
  • ConcreteClass(具体类)
    • 实现 AbstractClass 的抽象方法

类图如下:

拓展思路


可以使逻辑处理通用化

它的有点在于父类的模板方法中编写了算法,因此无需在每个子类再编写算法。

如果使用复制黏贴的方式,写了很多个 ConcreteClass 类,结果发现有一个bug,如果需要修改得全部修改。若使用 Template Method 模式,只需要修改父类中的模板方法即可。

父类与子类之间的协作

Template Method 模式中,父类和子类是密切联系的,因此在实现子类的同时,需要理解父类的方法。在看不到父类源代码的情况下,编写子类会比较困难。

父类与子类的一致性

无论在父类类型的变量中保存的是哪个子类的实例,程序都可以正常工作,这种原理称为“里氏替换原则”(The Liskov Subsitution Principle, LSP)。