模板方法模式:
把相似的流程抽象出来作为一个父类,来封装好子类的算法框架,然后子类继承这个父类,并且可以重写非公有的方法,来实现自己的业务逻辑。
聚个栗子
泡茶泡咖啡是很好的例子,不同企业的面试流程也是一个很好的例子
对于很多大型公司,比如BATTMD ,面试过程类似,先来简单假设一下面试过程:
- 笔试
- 技术面试
- HR面试
- 等通知
那么假如不久的将来我就要去面试了,拿即将上市的小米来举个例子(小白也有一个大厂梦啊),在JavaScript代码中意淫一下小米的面试流程
首先,定义一个小米面试的构造函数
var XiaomiInterview = function () {}
接下来,把面试的流程封装成它的方法
1.笔试
XiaomiInterview.prototype.writtenTest=function(){
console.log("看到小米的笔试题,紧张,激动~");
}
2.技术面
XiaomiInterview.prototype.technicalInterview=function(){
console.log("我是小米的前端技术负责人......");
}
3.HR面
XiaomiInterview.prototype.HRInterview = function (){
console.log("小米的HR小姐姐来面试我了,扑腾扑腾~");
}
4.等通知
XiaomiInterview.prototype.waitNotice=function(){
console.log("等得花儿都谢了,是不是凉凉了~");
}
现在代码的基本结构已经有了,再来为它初始化一个方法
XiaomiInterview.prototype.init=function(){
this.writtenTest();
this.technicalInterview();
this.HRInterview();
this.waitNotice();
}
实现它
var xiaomiInterview = new XiaomiInterview();
xiaomiInterview.init();
小米面试的基本流程如上面的代码,不管是BATTMD面试流程应该都跟这个类似,只是步骤的内容不一样,就不一一枚举了
那么不妨把流程抽象出来
接下来,就来改写一下前面的代码
首先定义一个类,就叫Interview
var Interview = function () {} //面试类
再抽象出方法
Interview.prototype.writtenTest=function(){
console.log("终于看到XX的笔试题了~");
}
Interview.prototype.technicalInterview=function(){
console.log("你好,我是XX的前端技术负责人");
}
Interview.prototype.HRInterview=function(){
console.log("XXHR来面试我了");
}
Interview.prototype.waitNotice=function(){
console.log("到现在都不给我通知,是不是凉凉了~");
}
Interview.prototype.init=function(){
this.writtenTest();
this.technicalInterview();
this.HRInterview();
this.waitNotice();
}
现在,创建一个XiaomiInterview子类来继承父类的算法框架
var XiaomiInterview = function () {}
XiaomiInterview.prototype = new Interview();
发现不管面哪一家,只有“等通知,凉凉”这一步是可以复用的T.T,所以我们需要重写子类不能复用的方法
XiaomiInterview.prototype.writtenTest=function(){
console.log("看到小米的笔试题,紧张,激动~");
}
XiaomiInterview.prototype.technicalInterview=function(){
console.log("我是小米的前端技术负责人......");
}
XiaomiInterview.prototype.HRInterview=function(){
console.log("小米的HR小姐姐来面试我了,扑腾扑腾~");
}
现在来实例化子类的对像
var xiaomiInterview = new XiaomiInterview();
xiaomiInterview.init();
抽象出来的模板类和子类已经完成了,这里直接调用xiaomiInterview.init()方法,xiaomiInterview本身并没有init()方法,但是它继承了父类,会迎着原型链到父类中查找。
如果还想继承其他子类,比如BAT面试类代码也是一样的。Interview.prototype.init() 是模板方法,他封装了子类中算法框架,它作为一个算法的模板,去指导子类以什么样的顺序去执行代码。
回顾一下刚才的代码,这是类式写法,在JavaScript中,可以写的更佳优雅
接下来,用js风格来表示上述的模板方法模式
创建Interview函数对象作为模板方法,它能接受一个JSON对象(传入子类需要重写的方法),创建一个F函数并给F函数添加init方法调用模板中的流程,最后返回F
var Interview = function (param) {
var writtenTest = param.writtenTest || function() {
throw new Error('必须传writtenTest方法');
}
var technicalInterview = param.technicalInterview || function() {
throw new Error('必须传technicalInterview方法');
}
var HRInterview = param.HRInterview || function() {
throw new Error('必须传HRInterview方法');
}
var waitNotice = function() {
console.log("到现在都不给我通知,是不是凉凉了~");
}
var F = function () {}
F.prototype.init = function () {
writtenTest();
technicalInterview();
HRInterview();
waitNotice();
}
return F;
}
重写XiaomiInterview无法复用的方法并传入到模板方法,来实现继承
var XiaomiInterview = Interview({
writtenTest:function(){
console.log("看到小米的笔试题,紧张,激动~");
},
technicalInterview:function(){
console.log("我是小米的前端技术负责人......");
},
HRInterview:function(){
console.log("小米的HR小姐姐来面试我了,扑腾扑腾~");
}
});
最后一步,完成xiaomiInterview
var xiaomiInterview = new XiaomiInterview();
xiaomiInterview.init();
完整的js风格代码
var Interview = function (param) {
var writtenTest = param.writtenTest || function() {
throw new Error('必须传writtenTest方法');
}
var technicalInterview = param.technicalInterview || function() {
throw new Error('必须传technicalInterview方法');
}
var HRInterview = param.HRInterview || function() {
throw new Error('必须传HRInterview方法');
}
var waitNotice = function() {
console.log("到现在都不给我通知,是不是凉凉了~");
}
var F = function () {}
F.prototype.init = function () {
writtenTest();
technicalInterview();
HRInterview();
waitNotice();
}
return F;
}
var XiaomiInterview = Interview({
writtenTest:function(){
console.log("看到小米的笔试题,紧张,激动~");
},
technicalInterview:function(){
console.log("我是小米的前端技术负责人......");
},
HRInterview:function(){
console.log("小米的HR小姐姐来面试我了,扑腾扑腾~");
}
});
var xiaomiInterview = new XiaomiInterview();
xiaomiInterview.init();
运行一下,查看结果,顺利完成了所有的流程
通过以上的实验,渐渐明白了,“别找我们,我们找你”这一著名的好莱坞原则描述的反向控制结构。子类放弃了对自己的控制权,而是改为父类通知子类,作为子类,只负责提供一些设计上的细节。制定算法骨架,让子类具体实现,这大概就是模板方法模式了吧