设计模式--装饰器模式

概念:

装饰模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。

其实,就是创建一个包装器,里面有增强的功能,然后把目标对象给套住,就直接使用包装器对象。

UML:

 es6:

class Circle {
    draw() {
        console.log("画一个圆形");
    }
}

class Decorator {
    constructor(circle){
        this.circle = circle;
    }
    draw() {
        this.circle.draw();
        this.setRedBorder(this.circle);
    }
    setRedBorder(circle) {
        console.log("设置红色边框")
    }
}
// 测试代码
let circle = new Circle();
let decorator= new Decorator(circle);
decorator.draw();

 es7:

function borderDecorator(target, key, descriptor) {
    const method = descriptor.value;
    
    descriptor.value = () => {
        method.apply(target);
        console.log("设置红色边框")
    }
    
    return descriptor;
}

class Circle {
    @borderDecorator
    draw() {
        console.log("画一个圆形");
    }
}


// 测试代码
let circle = new Circle();
circle.draw();

 对某个函数增强功能:

const memoize = function(f) {
        const cache = {};
        return function() {
            const argStr = JSON.stringify(arguments);
            
            if (!cache[argStr]) {
                cache[argStr] = f.apply(f, arguments);
            }
            
            return cache[argStr];
        }
    }

函数f没有缓存功能, 在没有修改原函数的情况下,通过闭包,套了一层,就具有缓存的功能了。

优点:

  • 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
  • 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。
  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”

缺点:

  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
  • 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
posted @ 2020-02-07 17:02  bigman-bugman  阅读(108)  评论(0编辑  收藏  举报