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()

// 输出:水已经煮沸
// 输出:冲泡咖啡
// 输出:倒进杯子里
// 输出:加点咖啡伴侣
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值