Template Method模式


title: Template Method模式
tag: 笔记 设计模式

image-20231019213450306

Template Method模式

Template Method模式是带有模板功能的模式组成模板的方法定义在父类中。由于这些方法是抽象方法,所以仅仅查看父类是不知道这些方法是如何进行具体处理的,我们只知道父类是符合调用它的。

实现上述这些抽象方法的是子类。在子类中实现了抽象方法也就决定了具体的处理。也就是说,只要在不同的子类中实现不同的具体处理,当父类的模板方法被调用时程序行为也会不同。但是,不论子类中的具体实现如何,处理的流程都会按照父类中所定义的那样进行。

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

示例程序

该实例程序会将字符和字符串循环显示5次的简单程序,我们会使用模板方法模式使字符和字符串有不同的处理。

该程序中有下面三个类:

  • AbstractDisplay
    • openprintclose三个抽象方法
    • display,调用了其它三个抽象方法,我们叫这个方法模板方法
  • CharDisplay:继承AbstractDisplay并实现抽象方法,处理字符。
  • StringDisplay:继承AbstractDisplay并实现抽象方法,处理字符串。
image-20231019213821258

AbstractDisplay类

public abstract class AbstractDisplay {
    protected abstract void open();

    protected abstract void print();

    protected abstract void close();
	//模板方法
    public final void display(){
        open();
        for (int i = 0; i < 5; i++) {
            print();
        }
        close();
    }
}

其中前面3个方法我们交由子类各自处理,我们可以知道的是模板方法display

  • 调用open方法
  • 调用5次print方法
  • 调用close方法

子类通过对3个抽象方法的不同实现,可以使程序具有不同的行为。其中模板方法我们使用final修饰是不想被子类重写。

CharDisplay类

public class CharDisplay extends AbstractDisplay{
    private char ch;
    public CharDisplay(char ch) {
        this.ch = ch;
    }

    @Override
    public void open() {
        System.out.print("<<");
    }

    @Override
    public void print() {
        System.out.print(ch);
    }

    @Override
    public void close() {
        System.out.print(">>");
    }
}

我们想要传入的字符像下面这样显示:

<>

我们通过重现父类的抽象方法来改变父类模板方法display的行为来实现。

StringDisplay类

public class StringDisplay extends AbstractDisplay{
    private String s;
    private int width;
    public StringDisplay(String s){
        this.s = s;
        this.width = s.length();
    }
    @Override
    public void open() {
        printLine();
    }

    @Override
    public void print() {
        System.out.print("|");
        System.out.print(s);
        System.out.println("|");
    }

    @Override
    public void close() {
        printLine();
    }
    private void printLine(){
        System.out.print("+");
        for (int i = 0; i < width; i++){
            System.out.print("-");
        }
        System.out.println("+");
    }
}

我们想要传入的字符串像下面这样显示:

±----------------+
|Hello,World!|
|Hello,World!|
|Hello,World!|
|Hello,World!|
|Hello,World!|
±-----------------+

与CharDisplay类一样,我们通过重写父类的抽象方法来改变模板方法display来实现上面的效果。

测试

public static void main(String[] args) {
    AbstractDisplay charDisplay = new CharDisplay('c');
    AbstractDisplay stringDisplay = new StringDisplay("Hello,World!");
    System.out.println("展示字符:");
    charDisplay.display();
    System.out.println();
    System.out.println("展示字符串:");
    stringDisplay.display();
}

输出:

展示字符:
<<ccccc>>
展示字符串:
+------------+
|Hello,World!|
|Hello,World!|
|Hello,World!|
|Hello,World!|
|Hello,World!|
+------------+

效果符合我们的预期。

我们使用AbstractDisplay类型的变量来接收两个子类的实例,并分别调用它们的display方法。Java的动态绑定机制会在子类中找到抽象方法的实现并使用。

Template Method模式中的角色

  • AbstractClass(抽象类):

AbstractClass角色不仅负责实现模板方法,还负责声明在模板方法中所使用到的抽象方法。这些抽象方法由子类ConcreteClass角色负责实现。在示例程序中,由AbstractDisplay类扮演此角色。

  • ConcrecteClass(具体类)

该角色负责具体实现AbstractClass角色中定义的抽象方法。这里实现的方法将会在AbstractClass角色的模板方法中被调用。在示例程序中,由CharDisplay类和StringDisplay类扮演此角色。

Template Method模式的类图:

image-20231019220816100

拓展思路

Template Method模式的好处

这样的设计模式优点是由于父类在模板方法中编写了算法,因此无需在每个子类中再编写算法。

我们也可以不使用这样的方法而是将复制粘贴编写多个ConcreteClass,此时若是出现了BUG的话我们就需要修改多处地方,而使用模板方法则仅仅只需要修改模板方法即可解决问题。

父类和子类之间的协作

Template Method模式中,父类和子类是紧密联系、共同工作的。因此,在子类中实现父类中声明的抽象方法时,必须要理解这些抽象方法被调用的时机。在看不到父类的源代码的情况下,想要编写出子类是非常困难的。

父类与子类的一致性

在示例程序中,不论是CharDisplay的实例还是StringDisplay的实例,都是先保存在AbstractDisplay类型的变量中,然后再来调用display方法的。
使用父类类型的变量保存子类实例的优点是,即使没有用instanceof等指定子类的种类,程序也能正常工作

无论父类类型的变量保存哪个子类的实例,程序都可以正常工作,这样的原则称为里氏替换原则。这是一种通用的继承原则。

相关的设计模式

  • Factory Method设计模式

Factory Method设计模式是将Template Method模式用于生成实例的一个例子。

  • Strategy模式

Template Method模式中,可以使用继承改变程序的行为。这是因为Template Method模式在父类中定义程序行为的框架,在子类中决定具体的处理。

这是一种通用的继承原则。

相关的设计模式

  • Factory Method设计模式

Factory Method设计模式是将Template Method模式用于生成实例的一个例子。

  • Strategy模式

Template Method模式中,可以使用继承改变程序的行为。这是因为Template Method模式在父类中定义程序行为的框架,在子类中决定具体的处理。

而在Strategy模式中,它可以使用委托改变程序的行为。与Template Method模式中改变部分程序行为不同的是,Strategy模式用于替换整个算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值