js-decorator(装饰着模式)

设计原则 开放-关闭原则:类应该对拓展开放,对修改关闭 设计的目标是允许类容易拓展,在不修改现有代码的情况下,就可搭配新的行为。

by sharon li

JavaScript

/**
* decorator 装饰者模式 
* 装饰者模式是动态地将责任附加到对象上。若要拓展功能,装饰者模式提供了比继承更有弹性的替代方案。
* 装饰者是一种实现继承的替代方案。
        .当脚本运行时,在子类中增加“行为”会影响原有类所有的实例,
        .而装饰者却不然。取而代之的是它能给不同对象各自添加新行为
* 通俗的说可以增加功能以及调整运行时的对象(每个装饰者都是一个对象),
  每个装饰者实际上都继承了目前已经被前一个装饰者进行增强后的对象。
* “其实就是给实例h化对象上增加功能”
* 比如素颜妹子为实体对象,那么画睫毛,口红,眼影都是装饰对象。
*/

// 简单的例子
function Macbook() {
    this.cost = function() {
        return 10000;
    };
    this.screenSize = function() {
        return 14;
    }
}
// 装饰1
function Memory(macbook) {
    var val = macbook.cost();
    this.cost = function() {
        return val + 1024;
    };
}
// 装饰2
function Cpu(macbook) {
    var val = macbook.cost();
    this.cost = function() {
        return val + 4;
    };
};
// 装饰3
function Disk(macbook) {
    var val = macbook.cost();
    this.cost = function() {
        return val + 5000;
    };
}

// var book = new Macbook();
// Memory(book);
// Cpu(book);
// Disk(book);
var book = new Disk(new Cpu(new Memory(new Macbook())));
console.log(book.cost());   // 16028 依次调用装饰者的cost方法

/**
 * 较复杂示例
 * 从父类构造函数增加装饰功能,利用空构造函数的实例对象继承父类构造函数的功能
 * 装饰者对象以父类构造函数的属性方式实现
*/
// 父类构造函数
function Sale(price) {
    this.price = price || 100;
}
// 原型的方法
Sale.prototype.getPrice = function() {
    return this.price;
};

// 装饰者 池子~ 各种装饰功能
Sale.decorators = {};

// 装饰功能1 个人所得税
Sale.decorators.persontax ={
    name : 'persontax',
    getPrice : function() {
        var price = this.uber.getPrice();
        price += price * 5 / 100;
        return price;
    }
};
// 装饰功能2 土地税
Sale.decorators.landtax = {
    name : 'landtax',
    getPrice : function() {
        var price = this.uber.getPrice();
        price += price * 200;
        return price;
    }
};
// 装饰功能3 格式化人民币
Sale.decorators.money = {
    name : 'money',
    getPrice : function() {
        return '¥' + this.uber.getPrice().toFixed(2);
    }
};

// 用来将各种功能赋给新实例
// 在newobj里我们设置了uber属性,便于子对象可以访问父对象。
// 然后再复制新的装饰者对象到newobj中,最后通过return返回一个经过装饰的对象
Sale.prototype.decorate = function(decorator) {
    var F = function()...