将相同的流程作为一个抽象类
Beverage.prototype.init = function(){this.boilWater();this.brew();this.pourInCup();this.addCondiments();};
使用场景
从大的方面来讲,模板方法模式常被架构师用于搭建项目的框架,架构师定好了框架的骨架, 程序员继承框架的结构之后,负责往里面填空,比如 Java 程序员大多使用过 HttpServlet 技术来 开发项目。
比如:
vue 或react的组件包含的生命周期
- created
- mounted
- beforeupdate
-
react
componentWillMound
- componentDidMound
- sholdComponentUpdate
- componentDidUpdate
- componentWillUnMount
钩子方法
通过模板方法模式,我们在父类中封装了子类的算法框架。这些算法框架在正常状态下是适 用于大多数子类的,但如果有一些特别“个性”的子类呢?比如我们在饮料类 Beverage 中封装了 饮料的冲泡顺序:
- 把水煮沸
- 用沸水冲泡饮料
- 饮料倒进杯子
- 加调料
这 4 个冲泡饮料的步骤适用于咖啡和茶,在我们的饮料店里,根据这 4 个步骤制作出来的咖 啡和茶,一直顺利地提供给绝大部分客人享用。但有一些客人喝咖啡是不加调料(糖和牛奶)的。 既然 Beverage 作为父类,已经规定好了冲泡饮料的 4 个步骤,那么有什么办法可以让子类不受这 个约束呢?
钩子方法 可以解决这个问题,放置钩子是隔离变化的一种常见手段。我们在父 类中容易变化的地方放置钩子,钩子可以有一个默认的实现,究竟要不要“挂钩”,这由子类自 行决定。钩子方法的返回结果决定了模板方法后面部分的执行步骤,也就是程序接下来的走向,这样一来,程序就拥有了变化的可能。
在这个例子里,我们把挂钩的名字定为 customerWantsCondiments,接下来将挂钩放入 Beverage 类,看看我们如何得到一杯不需要糖和牛奶的咖啡,代码如下:
var Beverage = function(){};Beverage.prototype.boilWater = function(){console.log( '把水煮沸' );};Beverage.prototype.brew = function(){throw new Error( '子类必须重写 brew 方法' );};Beverage.prototype.pourInCup = function(){throw new Error( '子类必须重写 pourInCup 方法' );};Beverage.prototype.addCondiments = function(){throw new Error( '子类必须重写 addCondiments 方法' );};Beverage.prototype.customerWantsCondiments = function(){return true; // 默认需要调料};Beverage.prototype.init = function(){this.boilWater();this.brew();this.pourInCup();if ( this.customerWantsCondiments() ){ // 如果挂钩返回 true,则需要调料this.addCondiments();}};var CoffeeWithHook = function(){};CoffeeWithHook.prototype = new Beverage();CoffeeWithHook.prototype.brew = function(){console.log( '用沸水冲泡咖啡' );};CoffeeWithHook.prototype.pourInCup = function(){console.log( '把咖啡倒进杯子' );};CoffeeWithHook.prototype.addCondiments = function(){console.log( '加糖和牛奶' );}CoffeeWithHook.prototype.customerWantsCondiments = function(){return window.confirm( '请问需要调料吗?' );};var coffeeWithHook = new CoffeeWithHook();coffeeWithHook.init();
