轻松掌握:JavaScript模板方法模式

模板方法模式

假如我们有一些对象,各个对象之间有一些相同的行为,也有一些不同的行为,这时,我们就可以用模板方法模式来把相同的部分上移到它们的共同原型中(父类),而将不同的部分留给自己各自重新实现。

模板方法:在这些平行对象的共同原型中定义的一个方法,它封装了子类的算法框架,它作为一个算法的模板,指导子类以何种顺序去执行哪些方法。

模板方法常常被架构师用于搭建项目的框架,架构师定好了框架的骨架,程序员们继承框架的结构后,负责往里面填空。

模板方法模式中,常常用到一个钩子方法:在父类中的容易变化的方法上放置钩子,模板方法依据钩子方法的返回值来决定是否执行容易变化的方法。

模板方法模式是一种基于继承的设计模式,但在JavaScript中也可以通过高阶函数来实现。
基于继承的模板方法模式:

//模板方法模式
//泡茶和冲咖啡,有相似的方法,也有不同的方法
//相似的方法在父类中实现,不同的方法在子类中各自重写
var Beverage = function () {};
Beverage.prototype.boilWater = function () {
    console.log('把水煮沸');
};
Beverage.prototype.pourMaterial = function (material) {
    console.log('把'+material+'倒进杯子');
};
Beverage.prototype.pourInCup = function () {
    console.log('把沸水倒进杯子');
};
Beverage.prototype.addCondiments = function () {
    throw new Error('子类必须自行实现该方法');
};
//钩子方法,是否需要加配料
Beverage.prototype.isWantCondiments = function () {
    return true; //默认为true,子类自行实现来改变返回值
};
//模板方法,规定了各个方法的执行顺序
Beverage.prototype.init = function (material) {
    this.boilWater();
    this.pourMaterial(material);
    this.pourInCup();
    if(this.isWantCondiments()){  //根据钩子方法的返回值决定是否执行
        this.addCondiments();
    }
};
//====子类
var Coffee = function () {};
Coffee.prototype = new Beverage(coffee);
Coffee.prototype.addCondiments = function () {
    console.log('加糖');
};
Coffee.prototype.isWantCondiments = function () {
    return window.confirm('请问需要加糖吗?');
};
//调用
var coffee = '咖啡粉';
var coffee1 = new Coffee();
coffee1.init(coffee);

通过高阶函数来实现:

var Beverage1 = function (obj,material) {
    var boilWater = function(){
        console.log('把水煮沸');
    };
    var pourMaterial = function(material){
        console.log('把'+material+'倒进杯子');
    };
    var pourInCup = function () {
        console.log('把沸水倒进杯子');
    };
    var addCondiments = obj.addCondiments||function () {
        throw new Error('子类必须自行实现该方法');
    };
    var isWantCondiments = obj.isWantCondiments||function () {
        return true; //默认为true,子类自行实现来改变返回值
    };
    var F = function(){};
    F.prototype.init = function(){
        boilWater();
        pourMaterial(material);
        pourInCup();
        if(isWantCondiments()){  //根据钩子方法的返回值决定是否执行
            addCondiments();
        }
    };
    return F;
};
//定义子类
var Coffee1 = Beverage1({
    addCondiments: function(){
        console.log('加糖');
    },
    isWantCondiments: function () {
        return window.confirm('请问需要加糖吗?');
    }
},'咖啡粉');
var Tea1 = Beverage1({
    addCondiments: function(){
        console.log('加柠檬');
    },
    isWantCondiments: function () {
        return window.confirm('请问需要加柠檬吗?');
    }
},'茶叶');
var aCupOfCoffee = new Coffee1();
aCupOfCoffee.init();
//把水煮沸
//把咖啡粉倒进杯子
//把沸水倒进杯子
//加糖(点确定)
var aCupOfTea = new Tea1();
aCupOfTea.init();
//把水煮沸
//把茶叶倒进杯子
//把沸水倒进杯子
//加柠檬(点确定)

参考文献: 《JavaScript模式》 《JavaScript设计模式与开发实践》

原文地址:https://www.cnblogs.com/susufufu/p/5811054.html