JavaScript 模板方法模式(es6)

经典的饮料与咖啡
先定义父类,子类继承通用的方法,特殊的方法在子类重写。

//父类咖啡
class Beverage {
    constructor(name) {
        //单独调用会报错,所以写constructor里面绑定this,this指向父类
        this.init = () => {
            this.boilWater();
            this.brew();
            this.pourInCup();
            if (this.customerWantsCondiments()) { // 如果挂钩返回 true,则需要调料
                this.addCondiments();
            }
        };
        console.log('构造函数的'+name)
    };
    //共用boilWater,子类不会修改它
    boilWater() {
        console.log('把水煮沸');
    };
    brew() {
        throw new Error('子类必须重写 brew 方法');
    };
    pourInCup() {
        throw new Error('子类必须重写 pourInCup 方法');
    };
    addCondiments() {
        throw new Error('子类必须重写 addCondiments 方法');
    };
    customerWantsCondiments() {
        return true; // 默认需要调料
    };
    //init也可以写在这里,解构之后单独调用时,在es5 ,this会指向window,在es6,this不会指向window,会报错
    // init() {
    //     console.log(this);
    //     this.boilWater();
    //     this.brew();
    //     this.pourInCup();
    //     if (this.customerWantsCondiments()) { // 如果挂钩返回 true,则需要调料
    //         this.addCondiments();
    //     }
    // };


}
//子类咖啡,继承父类饮料
class CoffeeWithHook extends Beverage {
    constructor(name) {
        //调用父类的构造函数,演示一下super怎么用,下面传了‘名字’字符串
        super(name);
    }
    brew() {
        console.log('用沸水冲泡咖啡');
    };
    pourInCup() {
        console.log('把咖啡倒进杯子');
    };
    addCondiments() {
        console.log('加糖和牛奶');
    };
    customerWantsCondiments() {
        return window.confirm('请问需要调料吗?');
    };

};

let coffeeWithHook = new CoffeeWithHook('名字');
//如果不把init写在constructor里面的,下面的解构会报错。在es5 ,this会指向window,在es6,this不会指向window,会报错
let {init} = coffeeWithHook;//var init = coffeeWithHook.init
init();

以下代码是传统的JavaScript的实现模板方法的代码,并不是说传统就不好。只是ES6已经有了类的概念,自然是提倡用类,让代码更清晰

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 coffee = new Coffee();
coffee.init();

你可能感兴趣的:(设计模式)