定义
模板模式(Template Pattern)属于行为型设计模式,会在父类定义一套固定的流程,这个流程包含各个行为执行的步骤顺序;子类通过去继承父类,将父类某些方法重写,从而实现具体的步骤方法。
适用场景
模板模式适合那种具有固定结构或者固定流程和标准的场景,那些与固定流程大同小异的行为可以进行重写,甚至不需要的流程可以不执行。如组装汽车、拼积木、包装礼物、房屋装修等。
举例说明
年底了,公司年会征集音乐类节目,蜘蛛侠被任命为总负责人。他将歌曲的组成分为了四个步骤,分别是前奏、主歌、副歌、结尾,所有来彩排的表演者都需要根据这个模板的标准设计节目内容。
热爱音乐的金刚狼和绿巨人踊跃报名, 他们都需要根据这个标准流程设计自己的歌曲内容。于是金刚狼和绿巨人分别根据模板,设计出了自己节目特定的前奏、主歌、副歌及结尾。
代码实现
这种固定行为和步骤的方式非常适合模板模式。整体思路很简单,设计一个抽象类,定义行为和执行顺序;再设计每一个具体类,继承抽象类再重写抽象类中的所有行为。
定义一个抽象类Temp,把前奏、主歌、副歌、结尾的抽象方法定义,这些方法需要在子类去实现;另外需要定义一个步骤执行方法start,用来规定这些方法的执行顺序。
再分别定义金刚狼和绿巨人的表演类,这些类都继承于Temp,需要将前奏、主歌、副歌、结尾这些抽象方法具像化,同时每个类都继承了start。
// 定义一个抽象类模板 abstract class Temp{ // 前奏 abstract intro():void; // 主歌 abstract verse():void; // 副歌 abstract chorus():void; // 结尾 abstract outro():void; // 初始化步骤 start():void{ this.intro(); this.verse(); this.chorus(); this.outro(); } } // 金刚狼表演类 class Wolf extends Temp{ constructor() { super(); } intro():void{ console.log('金刚狼-前奏用军鼓渐强递进'); } verse():void{ console.log('金刚狼-主歌用四二拍常规节奏型'); } chorus():void{ console.log('金刚狼-副歌用四二拍轻快节奏型'); } outro():void{ console.log('金刚狼-吊镲加过骨渐慢收尾'); } } // 绿巨人表演类 class Hulk extends Temp{ constructor() { super(); } intro():void{ console.log('绿巨人-前奏吉他分解solo'); } verse():void{ console.log('绿巨人-主歌吉他分解和弦弹唱'); } chorus():void{ console.log('绿巨人-副歌吉他扫弦弹唱'); } outro():void{ console.log('绿巨人-结尾吉他分解solo加泛音'); } } const wolf = new Wolf(); const hulk = new Hulk(); wolf.start(); hulk.start();
当客户端生成两个表演类实例后,用实例去调用各自的start方法,就会把实例中的intro、verse、chorus、outro方法按顺序调用。
钩子方法
一些情况可能不需要中间的某一步或几步。绿巨人突然发现,自己要演奏的歌曲如果直接开始主歌效果更好,所以就尝试一下,如何不执行前奏才能直接进入主歌部分。
这种特殊场景,需要自定义是否执行某些方法,重写出来的函数称为“钩子方法”。根据例子,Temp类中可以定义一个doIntro方法,默认return true,start方法中添加一个if判断分支;子类中重写这个doIntro方法 return false,客户端再调用就不会执行了。
// 定义一个抽象类模板 abstract class Temp{ // 前奏 abstract intro():void; // 主歌 abstract verse():void; // 副歌 abstract chorus():void; // 结尾 abstract outro():void; // 初始化步骤 start():void{ this.intro(); this.verse(); this.chorus(); this.outro(); } // 是否执行前奏 doIntro():boolean { return true; } } // 绿巨人表演类 class Hulk extends Temp{ constructor() { super(); } intro():void{ console.log('绿巨人-前奏吉他分解solo'); } verse():void{ console.log('绿巨人-主歌吉他分解和弦弹唱'); } chorus():void{ console.log('绿巨人-副歌吉他扫弦弹唱'); } outro():void{ console.log('绿巨人-结尾吉他分解solo加泛音'); } doIntro():boolean { return false; } } const hulk = new Hulk(); hulk.start();
总结
模板模式是一种经典的抽象思想,旨在将一系列类似行为的共性行为抽出,作为抽象逻辑,个性行为会作为重写的个性呈现,这样有利于提取公共代码,减少重复逻辑。前端必须掌握的设计模式系列持续更新,如果对您有帮助希望多多点赞哦!