TypeScript版 模板方法模式

如何理解模板方法模式

准备食材(肉、蔬菜)
食材放到锅里
放调味料(糖、盐、油)
炒菜
倒到容器里(盘子、碗)
========================
先把水煮沸
冲泡饮料(咖啡、茶、牛奶)
倒进杯子中
最后加一些调味料(咖啡伴侣、糖)

在类似的场景中,这些例子都有这些特点:

有一个基本的操作流程,这个流程我们可以抽象出来,由具体实例的操作流程来实现,比如做咖啡的时候冲泡的就是咖啡,做茶的时候冲泡的就是茶;
一些共用的流程,就可以使用通用的公共步骤,比如把水煮沸,比如将食材放到锅里,这样的共用流程就可以共用一个具体方法就可以了;

**

模板方法模式:

**
在这里插入图片描述

abstract class AbstractClass {
    
    
    constructor() {
    
    }

    // 模板方法
    public template() : void {
    
    
        this.operation1();
        this.hookMethod() && this.operation2();
        this.operation3();
    }

    // 基本方法
    protected operation1() : void {
    
    
        console.log('使用了方法operation1');
    }

    protected operation2() : void {
    
    
        console.log('使用了方法operation2');
    }

    protected operation3() : void {
    
    
        console.log('使用了方法operation3');
    }

    // 钩子方法
    protected hookMethod() : boolean {
    
    
        return true;
    }
}

class ConcreteClassA extends AbstractClass {
    
    
    protected operation2() :void {
    
    
        console.log('对该方法operation2进行了修改再使用');
    }

    protected operation3() :void {
    
    
        console.log('对该方法operation3进行了修改再使用');
    }
}

class ConcreteClassB extends AbstractClass {
    
    
    // 覆盖钩子方法
    protected hookMethod() : boolean {
    
    
        return false;
    }
}

function main() {
    
    
    const class1 : AbstractClass = new ConcreteClassA();
    const class2 : AbstractClass = new ConcreteClassB();

    class1.template();
    console.log('==========================')
    class2.template();
}

main();

在这里插入图片描述

模板方法模式的优缺点

模板方法模式的优点:

  1. 封装了不变部分,扩展可变部分, 把算法中不变的部分封装到父类中直接实现,而可变的部分由子类继承后再具体实现;
  2. 提取了公共代码部分,易于维护, 因为公共的方法被提取到了父类,那么如果我们需要修改算法中不变的步骤时,不需要到每一个子类中去修改,只要改一下对应父类即可;
    3.行为被父类的模板方法固定, 子类实例只负责执行模板方法,具备可扩展性,符合开闭原则;

模板方法模式的缺点:增加了系统复杂度,主要是增加了的抽象类和类间联系,需要做好文档工作;

其他相关模式

模板方法模式与工厂模式
模板方法模式的实现可以使用工厂模式来获取所需的对象。

另外,模板方法模式和抽象工厂模式比较类似,都是使用抽象类来提取公共部分,不一样的是:

  1. 抽象工厂模式 提取的是实例的功能结构;
  2. 模板方法模式 提取的是算法的骨架结构;

tip:另外一个更好的例子

/* 饮料类,父类 */
class Beverage {
    
    
    constructor() {
    
    
        if (new.target === Beverage) {
    
    
            throw new Error('抽象类不能直接实例化!')
        }
    }
  
    /* 烧开水,共用方法 */
    boilWater() {
    
     console.log('水已经煮沸') }
    
    /* 冲泡饮料,抽象方法 */
    brewDrink() {
    
     throw new Error('抽象方法不能调用!') }
    
    /* 倒杯子里,共用方法 */
    pourCup() {
    
     console.log('倒进杯子里') }
    
    /* 加调味品,抽象方法 */
    addCondiment() {
    
     throw new Error('抽象方法不能调用!') }
    
    /* 制作流程,模板方法 */
    init() {
    
    
        this.boilWater()
        this.brewDrink()
        this.pourCup()
        this.addCondiment()
    }
}

/* 咖啡类,子类 */
class Coffee extends Beverage {
    
    
    constructor() {
    
     super() }
    
    /* 冲泡饮料,实现抽象方法 */
    brewDrink() {
    
     console.log('冲泡咖啡') }
    
    /* 加调味品,实现抽象方法 */
    addCondiment() {
    
     console.log('加点咖啡伴侣') }
}

const coffee = new Coffee()
coffee.init()

// 输出:水已经煮沸
// 输出:冲泡咖啡
// 输出:倒进杯子里
// 输出:加点咖啡伴侣

猜你喜欢

转载自blog.csdn.net/weixin_40121676/article/details/107979747
今日推荐