模板方法模式
模板方法模式是一种使用继承实现的简单模式。
模板方法模式由两部分组成,第一部分是抽象父类,第二部分是具体实现子类。
具体实现子类需要对抽象父类定义的方法进行重写。
JavaScript 模仿继承实现
使用 vue-cli 可以创建 vue2 项目或者 vue3 项目,创建项目的过程大致一样,只是需要选择不同的 vue 版本,这个时候可以用模板方法模式来封装变化。
function createVueApp() {}
createVueApp.prototype.execCreateCommand = function() {
console.log('execCreateCommand');
};
createVueApp.prototype.chooseVueVersion = function() {
throw new Error('请重写函数');
};
createVueApp.prototype.init = function() {
this.execCreateCommand();
this.chooseVueVersion();
};
function createVue2App() {}
createVue2App.prototype = new createVueApp();
createVue2App.prototype.chooseVueVersion = function() {
console.log('选择 vue2');
};
createVue2App.prototype.init();
function createVue3App() {}
createVue3App.prototype = new createVueApp();
createVue3App.prototype.chooseVueVersion = function() {
console.log('选择 vue3');
};
createVue3App.prototype.init();
用 JavaScript 实现模板方法模式具有一些缺陷。第一就是 JavaScript 没有继承,JavaScript 中使用 prototype 原型链实现伪继承,更准确的说法应该是委托;第二是 JavaScript 中没有抽象方法和类型系统,于是不能确定子类是否重写了父类方法。这个问题由两个解决方案,第一是鸭子类型检查,第二是实例代码中由父类抛出错误。
JavaScript 高阶函数实现
由于函数在 JavaScript 中是一等公民,可以当成参数传递。所以可以使用高阶函数的形式实现模板方法模式。
function createVueApp(param) {
const execCreateCommand = function() {
console.log('execCreateCommand');
};
const chooseVueVersion =
param.chooseVueVersion ||
function() {
throw new Error('请重写函数');
};
const F = function() {};
F.prototype.init = function() {
execCreateCommand();
chooseVueVersion();
};
return F;
}
const createVue2App = createVueApp({
chooseVueVersion: function() {
console.log('选择 vue2');
},
});
const createVue3App = createVueApp({
chooseVueVersion: function() {
console.log('选择 vue3');
},
});
模板方法模式其实就是封装不变的部分到父类,变化的部分由子类自己实现。他是一种典型的通过封装系统变化提高系统扩展性的设计模式。在 JavaScript 中,使用高阶函数实现模板方法模式是一种更好的选择。