企业网站建设一条龙多少钱,网站放自己服务器备案,能不能用自己的主机做网站,东莞长安做网站公司JavaScript模板方法模式 1 什么是模板方法模式2 Coffee or Tea3 钩子方法4 好莱坞原则 1 什么是模板方法模式
模板方法模式是一种只需使用继承就可以实现的模式。
模板方法模式由两部分结构组成#xff0c;第一部分是抽象父类#xff0c;第二部分是具体的实现子类。
通常在… JavaScript模板方法模式 1 什么是模板方法模式2 Coffee or Tea3 钩子方法4 好莱坞原则 1 什么是模板方法模式
模板方法模式是一种只需使用继承就可以实现的模式。
模板方法模式由两部分结构组成第一部分是抽象父类第二部分是具体的实现子类。
通常在抽象父类中封装了子类的算法框架包括实现一些公共方法以及封装子类中所有方法的执行顺序。子类通过继承这个抽象类也继承了整个算法结构并且可以选择重写父类的方法。
2 Coffee or Tea
接下来通过咖啡与茶这个经典的例子来说明模版方法模式。
首先我们想泡一杯咖啡泡咖啡的步骤通常如下
把水煮沸用沸水冲泡咖啡将咖啡倒入杯子中添加糖和牛奶
将上述步骤写成代码描述出来具体如下
var Coffee function () {};Coffee.prototype.boilWater function () {console.log(把水煮沸);
};Coffee.prototype.brewCoffeeGriends function () {console.log(用沸水冲泡咖啡);
};Coffee.prototype.pourInCup function () {console.log(把咖啡倒进杯子);
};Coffee.prototype.addSugarAndMilk function () {console.log(加糖和牛奶);
};Coffee.prototype.init function () {this.boilWater();this.brewCoffeeGriends();this.pourInCup();this.addSugarAndMilk();
};var Coffee new Coffee();
Coffee.init();接下来我们泡一壶茶泡茶的步骤和泡咖啡的步骤基本相同
把水煮沸用沸水浸泡茶叶将茶水倒入杯子中添加柠檬
同样用一段代码来实现泡茶的步骤
var Tea function () {};Tea.prototype.boilWater function () {console.log(把水煮沸);
};Tea.prototype.steepTeaBag function () {console.log(用沸水浸泡茶叶);
};Tea.prototype.pourInCup function () {console.log(把茶水倒进杯子);
};Tea.prototype.addLemon function () {console.log(加柠檬);
};Tea.prototype.init function () {this.boilWater();this.steepTeaBag();this.pourInCup();this.addLemon();
};var tea new Tea();
tea.init();经过对比泡咖啡和泡茶的过程我们发现两者的步骤好像差不多但是有如下不同点
原料不同。一个是咖啡一个是茶但我们可以把它们都抽象为“饮料”泡的方式不同。咖啡是冲泡而茶叶是浸泡我们可以把它们都抽象为“泡”加入的调料不同。一个是糖和牛奶一个是柠檬但我们可以把它们都抽象为“调料”
经过抽象之后不管是泡咖啡还是泡茶我们都能整理为下面四步
把水煮沸用沸水冲泡饮料将饮料倒入杯子中添加调味料
根据上述共同点我们可以创建一个抽象父类来表示泡一杯饮料的整个过程。不论是Coffee还是Tea都用Beverage来表示代码如下
Beverage.prototype.boilWater function () {console.log(把水煮沸);
};Beverage.prototype.brew function () {}; // 冲泡动作Beverage.prototype.pourInCup function () {}; // 倒入杯子Beverage.prototype.addCondiments function () {}; // 添加调料Beverage.prototype.init function () {this.boilWater();this.brew();this.pourInCup();this.addCondiments();
};接下来我们创建咖啡类和茶类并让它们继承饮料类
var Coffee function () {};
Coffee.prototype new Beverage();// 重写父类方法
Coffee.prototype.brew function () {console.log(用沸水冲泡咖啡);
};
Coffee.prototype.pourInCup function () {console.log(把咖啡倒进杯子);
};
Coffee.prototype.addCondiments function () {console.log(加糖和牛奶);
};var Coffee new Coffee();
Coffee.init();var Tea function () {};
Tea.prototype new Beverage();// 重写父类方法
Tea.prototype.steepTeaBag function () {console.log(用沸水浸泡茶叶);
};
Tea.prototype.pourInCup function () {console.log(把茶水倒进杯子);
};
Tea.prototype.addCondiments function () {console.log(加柠檬);
};var tea new Tea();
tea.init();在上面的例子中Beverage.prototype.init就是模板方法因为该方法中封装了子类的算法框架它作为一个算法的模板指导子类以何种顺序去执行哪些方法。
3 钩子方法
通过模板方法模式我们在父类中封装了子类的算法框架。这些算法框架在正常状态下是适用于大多数子类的但如果有一些特别“个性”的子类呢比如有一些客人喝咖啡是不加调料糖和牛奶的。
既然Beverage作为父类已经规定好了冲泡饮料的4个步骤那么有什么办法可以让子类不受这个约束呢
钩子方法可以用来解决这个问题放置钩子是隔离变化的一种常见手段。我们在父类中容易变化的地方放置钩子钩子可以有一个默认的实现究竟要不要“挂钩”这由子类自行决定。钩子方法的返回结果决定了模板方法后面部分的执行步骤也就是程序接下来的走向这样一来程序就拥有了变化的可能。
接下来将挂钩customerWantsCondiments放入Beverage类看看我们如何得到一杯不需要糖和牛奶的咖啡代码如下
var Beverage function () {};
Beverage.prototype.boilWater function () {console.log(把水煮沸);
};
Beverage.prototype.brew function () {}; // 冲泡动作
Beverage.prototype.pourInCup function () {}; // 倒入杯子
Beverage.prototype.addCondiments function () {}; // 添加调料
Beverage.prototype.customerWantsCondiments function () {return true; // 默认需要调料
};
Beverage.prototype.init function () {this.boilWater();this.brew();this.pourInCup();if (this.customerWantsCondiments()) { // 如果返回true表示需要调料this.addCondiments();}
};var Coffee function () {};
Coffee.prototype new Beverage();
// 重写父类方法
Coffee.prototype.brew function () {console.log(用沸水冲泡咖啡);
};
Coffee.prototype.pourInCup function () {console.log(把咖啡倒进杯子);
};
Coffee.prototype.addCondiments function () {console.log(加糖和牛奶);
};
Coffee.prototype.customerWantsCondiments function () {return window.confirm(请问需要调料吗);
};
var Coffee new Coffee();
Coffee.init();4 好莱坞原则
JS好莱坞原则的基本思想是高层组件通过调用底层组件暴露的接口来控制底层组件的行为而底层组件不应该直接依赖或调用高层组件的实现。
这个原则的名字来源于好莱坞电影制片厂因为在好莱坞电影中明星演员通常是高层组件而服装、化妆等其他组件则是底层组件。这些底层组件在电影制作过程中由高层组件来控制和协调。
在这一原则的指导下我们允许底层组件将自己挂钩到高层组件中而高层组件会决定什么时候、以何种方式去使用这些底层组件。
模板方法模式是好莱坞原则的一个典型使用场景它与好莱坞原则的联系非常明显当我们用模板方法模式编写一个程序时就意味着子类放弃了对自己的控制权而是改为父类通知子类哪些方法应该在什么时候被调用。作为子类只负责提供一些设计上的细节。
在好莱坞原则的指导之下下面这段代码可以达到和继承一样的效果。
var Beverage function (param) {var boilWater function () {console.log(把水煮沸);};var brew param.brew; // 冲泡动作var pourInCup param.pourInCup; // 倒入杯子var addCondiments param.addCondiments; // 添加调料var F function () {};F.prototype.init function () {boilWater();brew();pourInCup();addCondiments();};return F;
};var Coffee Beverage({brew: function () {console.log(用沸水冲泡咖啡);},pourInCup: function () {console.log(把咖啡倒进杯子);},addCondiments: function () {console.log(加糖和牛奶);},
});var Tea Beverage({brew: function () {console.log(用沸水浸泡茶叶);},pourInCup: function () {console.log(把茶倒进杯子);},addCondiments: function () {console.log(加柠檬);},
});var coffee new Coffee();
coffee.init();
var tea new Tea();
tea.init();在这段代码中我们把brew、pourInCup、addCondiments这些方法依次传入Beverage函数Beverage函数被调用之后返回构造器F。F类中包含了“模板方法”F.prototype.init。跟继承得到的效果一样该“模板方法”里依然封装了饮料子类的算法框架。