装饰者模式

1.jquery $('.a').find('.b')  , $('.a') 以后返回一个对象, find('.b') 以后 也是返回一个对象,对$('.a')装饰一个方法 find , $('.a').find('.b') 再加一个装饰 width(); 返回的仍然是一个完整的jquery的对象

这就是装饰者模式。

参考书:[JavaScript模式].Stoyan.Stefanov  =》第153页

所以可以初步理解为,一个对象,有很多方法,每次调用以后,任然返回一个完整的值被方法装饰过的对象。能实现这样的功能,就是装饰者模式。所以可以自己来实现一下。

假设,有个对象 obj,修改它的长度为100,obj.changeLength(100), 再次计算它的平方根号
为100*100. obj.changeLength(100).Math("sqr")或者 100+100 obj.changeLength(100).Math("add") ,(100+100)*(100 + 100)
obj.changeLength(100).Math("add").Math('sqr') 返回结果。
那么每次调用之后,返回的都是一个对象,要如何实现,这个对象的构造方法?

function setObj(width){
        this.width = 100||width;
    }
    setObj.prototype.setWidth = function(){
        return this.width + 'px';
    }

    setObj.prototype.changeLength = function(width){
        this.width = width;
        return this;
    }

    setObj.prototype.Math = function(value){
        if(value == 'add'){
            this.width = this.width + this.width;
        }else if(value == 'sqr'){
            this.width = this.width * this.width;
        }
        return this;
    }


    var newobj = new setObj(120);
    console.log(newobj.changeLength(200).Math("add").Math("sqr").setWidth());
   console.log(newobj.changeLength(200).Math("add").setWidth());

打印的 160000px 这样就能实现了,这样随便调用什么方法,都是返回的一个完整的对象。

但是这样写有个问题,就是Math("add")方法实际框架中,可能会包含很多计算,修改很多值,所以嵌套在if里面无法维护。修改

setObj.prototype.Math 不返回 this, 返回一个对 setObj 的继承,和方法的重写。不去改变初始参数this.width的值。
    function setObj(width){
        this.width = width||100;
    }
    setObj.prototype.getWidth = function(){
        return this.width;
    }

    setObj.prototype.changeLength = function(width){
        this.width = width;
        return this;
    }
    
    setObj.Maths = {};
    setObj.Maths.add = {
        getWidth: function() {
            console.log(this);
            return this.getWidth()+'%';
        }
    }
    
    setObj.Maths.sqr = {
        getWidth: function() {
            return this.getWidth()+'px';
        }
    }

    setObj.prototype.Math = function(value){
        var F = function(){};
        var overObj = this.constructor.Maths[value];
        F.prototype = this; // F构造函数继承setObj
        var newObj = new F();
        
        for(var i in overObj){
            console.log(i);
            if(overObj.hasOwnProperty(i)){
                newObj[i] = overObj[i];
            }
        }
        return newObj;
    }


    var newobj = new setObj(120);
    console.log(newobj.Math("add"));

这样写完以后,就会出现一个问题,

getWidth 不停的回调 自己。死循环了,所以找一个变量寄存一下原来的 getWidth方法
 
function setObj(width){
        this.width = width||100;
    }
    setObj.prototype.getWidth = function(){
        return this.width;
    }

    setObj.prototype.changeLength = function(width){
        this.width = width;
        return this;
    }
    
    setObj.Maths = {};
    setObj.Maths.add = {
        getWidth: function() {
            return this.uber.getWidth() + this.uber.getWidth();
        }
    }
    
    setObj.Maths.sqr = {
        getWidth: function() {
            return this.uber.getWidth() * this.uber.getWidth();
        }
    }

    setObj.prototype.Math = function(value){
        var F = function(){};
        var overObj = this.constructor.Maths[value];
        F.prototype = this; // F构造函数继承setObj
        var newObj = new F();
        newObj.uber = F.prototype;
        
        for(var i in overObj){
            if(overObj.hasOwnProperty(i)){
                newObj[i] = overObj[i];
            }
        }
        return newObj;
    }


    var newobj = new setObj(120);
    console.log(newobj.Math("add").Math("sqr").getWidth());

看一下官方案列

function Sale(price){
        this.price = price || 100;
    }

    Sale.prototype.getPrice = function(){
        return this.price;
    }

    Sale.decorators = {};

    Sale.decorators.fedtax = {
        getPrice: function(){
            var price = this.uber.getPrice();
            price += price *7.5 / 100;
            return price;
        }
    }

    Sale.decorators.money = { //把方法挂在在构造函数上面,这样这个方法就属于这个构造里面
        getPrice: function() {
            return "$" + this.uber.getPrice().toFixed(2);
        }
    }

    Sale.decorators.cdn = {
        getPrice: function() {
            return "CDN$" + this.uber.getPrice().toFixed(2);
        }
    }

    Sale.prototype.decorate = function(decorator){
        var F = function(){},
            overrides = this.constructor.decorators[decorator],
            i, newobj;
        F.prototype = this;
        newobj = new F();
        newobj.uber = F.prototype; //newobj拥有了F对象的所有方法
        for(i in overrides){
            if(overrides.hasOwnProperty(i)){ //重写getPrice方法
                newobj[i] = overrides[i];
            }
        }
        return newobj;
    }

    var sale = new Sale(100);
    var back = sale.decorate("fedtax").decorate("money");

看一下jquery里面是怎么使用的

无论调用什么,返回的都是

posted on 2020-08-10 17:37  chenyi4  阅读(137)  评论(0编辑  收藏  举报

导航