Skip to content

Latest commit

 

History

History
141 lines (133 loc) · 4.27 KB

08模板方法模式.md

File metadata and controls

141 lines (133 loc) · 4.27 KB

模板方法模式

模板方法模式是一种只需使用继承通过封装变化提高系统扩展性的设计模式

  • 抽象父类:公共方法以及封装子类中所有方法的执行顺序
  • 子类:继承这个抽象类

例子

泡咖啡

  1. 把水煮沸
  2. 用沸水冲泡咖啡
  3. 把咖啡倒进杯子
  4. 加糖和牛奶

泡茶

  1. 把水煮沸
  2. 用沸水浸泡茶叶
  3. 把茶水倒进杯子
  4. 加柠檬

提取:

  1. 把水煮沸
  2. 用沸水冲泡饮料
  3. 把饮料倒进杯子
  4. 加调料

继承

/*创建一个抽象父类来表示泡一杯饮料的整个过程。
不论是 Coffee,还是 Tea,都被我们用Beverage来表示*/
var Beverage = function(){};
Beverage.prototype.boilWater = function(){ 
    console.log( '把水煮沸' );
};
Beverage.prototype.brew = function(){
    throw new Error( '子类必须重写 brew 方法' );
}; 
Beverage.prototype.pourInCup = function(){
    throw new Error( '子类必须重写 pourInCup 方法' );
}; 
Beverage.prototype.addCondiments = function(){
    throw new Error( '子类必须重写 addCondiments 方法' );
};
Beverage.prototype.init = function(){ 
    this.boilWater();
    this.brew();
    this.pourInCup(); 
    this.addCondiments();
};
/*创建Coffee类*/
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();
/*创建Tea 类*/
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( '加柠檬' );
};
var tea = new Tea(); 
tea.init();

非继承

好莱坞原则:新人演员在好莱坞把简历递给演艺公司之后就只有回家等待电话,有时候该演员等得不耐烦了,给演艺公司打电 话询问情况,演艺公司往往这样回答:“不要来找我,我会给你打电话。

应用:(子类放弃了对自己的控制权,而是改为父类通知子类)

  • 发布—订阅模式
  • 回调函数
var Beverage = function( param ){
    var boilWater = function(){ 
        console.log( '把水煮沸' );
    };
    var brew = param.brew || function(){  
        throw new Error( '必须传递 brew 方法' );
    };
    var pourInCup = param.pourInCup || function(){ 
        throw new Error( '必须传递 pourInCup 方法' );
    };
    var addCondiments = param.addCondiments || function(){ 
        throw new Error( '必须传递 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();

小结

模板方法模式是一种典型的通过封装变化提高系统扩展性的设计模式。 在传统的面向对象语言中,一个运用了模板方法模式的程序中,子类的方法种类和执行顺序都是不变的,所以我们把这部分逻辑抽象到父类的模板方法里面。 而子类的方法具体怎么实现则是可变的,于是我们把这部分变化的逻辑封装到子类中。 通过增加新的子类,我们便能给系统增加新的功能,并不需要改动抽象父类以及其他子类,这也是符合开放-封闭原则的。 但在 JavaScript 中,我们很多时候都不需要依样画瓢地去实现一个模版方法模式,高阶函数是更好的选择。