设计模式之模板方法模式

Posted by franki on November 7, 2018

模板方法模式

模板方法模式是一种只用继承就可以实现非常简单的模式

主要思想是: 抽象父类,具体实现子类,在父类主要是封装了子类的算法框架一些公共的方法的以及子类的执行顺序。子类通过继承这个抽象类,也继承了整个算法结构,并且可以选择重写父类的方法。

// Coffee or Tea

// 模拟传统面向对象的形式实现
// 父类
var Beverage = function() {}

Beverage.prototype.boilWater = function() {console.log('把水煮沸');} // 通用方法

Beverage.prototype.brew = function() {throw new Error('必须重写改方法');} // 需要重写的方法

Beverage.prototype.pourInCup = function(){throw new Error('必须重写改方法');} // 需要重写的方法

Beverage.prototype.addCondiments = function(){throw new Error('必须重写改方法');} // 需要重写的方法

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.brew = function() {console.log('用沸水冲泡茶');}
Tea.prototype.pourInCup = function(){console.log('把茶倒进杯子');}
Tea.prototype.addCondiments = function(){console.log('加柠檬');}
// 把水煮沸
// 用沸水冲泡茶
// 把茶倒进杯子
// 加柠檬

好莱坞规则,新人有时接不到戏会打电话到公司询问,而公司却不想为此费事,只会提示“我到时会通知你,你不用打电话来”,其实这就是基于高层组件对于底层组件的调用的一种体现。

模板方法模式就是基于继承的设计模式,但js并未提供真正的类式继承,继承是通过对象与对象的委托实现的。父类封装的了子类算法框架与执行顺序,子类继承父类后,父类通知子类去执行这些方法,好莱坞规则完美的诠释了这样设计技巧。

// 例子:
var Beverage = function(params) {
    var boilWater = function() {
        console.log('把水煮沸');
    }
    var brew = params.brew || function() {

    }
    var pourInCup = params.pourInCup || function() {

    }
    var addCondiments = params.addCondiments || function(){

    }

    var customerHook = params.customerHook || function() {
        return true;
    }

    var F = function() {};
        F.prototype.init = function() {
        boilWater();
        brew();
        pourInCup();
        if (customerHook()) {
            addCondiments();
        }
    }

    return F;
}


var Tea = Beverage({
    brew: function(){
        console.log('用沸水冲泡茶');
    },
    pourInCup: function(){
        console.log('把茶倒入杯子');
    },
    addCondiments: function(){
        console.log('加柠檬');
    },
    addCondiments: function(){
        return true;
    }
});
var tea = new Tea();
Tea.init();
// 把水煮沸
// 用沸水冲泡茶
// 把茶倒入杯子
// 加柠檬

var Coffee = Beverage({
    brew: function(){
        console.log('用沸水冲泡咖啡');
    },
    pourInCup: function(){
        console.log('把咖啡倒入杯子');
    },
    addCondiments: function(){
        console.log('加糖和牛奶');
    },
    addCondiments: function(){
        return false;
    }
});
var coffee = new Coffee();
coffee.init();
// 把水煮沸
// 用沸水冲泡咖啡
// 把咖啡倒入杯子