Skip to content

8、模板方法模式

案例

  • 咖啡与茶 组成
  • 抽象父类(封装子类算法框架:公共方法、子类所有方法执行顺序)
  • 具体实现子类(继承整个算法结构,可以选择重写父类方法)

模板方法 是 Beverage.prototype.init

如果我们的Coffee类或者Tea类忘记实现这4个方法中的一个呢?

  • 让Beverage.prototype.brew等方法直接抛出一个异常

钩子方法 (应对变化)

  • 隔离变化的一种常见手段
  • 我们在父类中容易变化的地方放置钩子,
  • 钩子可以有一个默认的实现,究竟要不要“挂钩”,这由子类自行决定。
  • 钩子方法的返回结果决定了模板方法后面部分的执行步骤,也就是程序接下来的走向

好莱坞原则 - 模板方法模式:子类放弃了对自己的控制权,而是改为父类通知子类,哪些方法应该在什么时候被调用

js
    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();