设计模式之装饰模式

冬天已经来临,北方的小伙伴们是否是感受天气一天比一天冷了呢?从秋天过渡到冬天,冷了就穿一件毛衣,若是穿上毛衣还以为冷可能会添一件羽绒服,若是下雪天可能就须要穿上雨衣或者带上雨伞了。在咱们生活中这些衣服以拓展的方式给了你温暖,可是它们并非你的一部分,若是到了春天那么这些衣服可能会一一的脱掉了。学习

在软件开发过程当中,有事想用一些现存的类或者组件,这些类或者组件可能只是完成了一些核心功能。但在不改变其结构的状况下,能够动态的拓展其功能。全部这些均可以用装饰模式来实现。this

什么装饰模式

装饰模式:指的是在没必要改变原类文件和使用继承的状况下,动态地扩展一个对象的功能。它是经过建立一个包装对象,也就是装饰来包裹真实的对象。 —— 节选自百度百科编码

装饰模式有两种方式能够实现给一个类或者一个对象添加行为,第一种是使用继承,使用继承是给现有类添加功能的一种有效途径,经过继承一个现有类能够使得子类在拥有自身方法的同时还拥有父类的方法。可是这种方法是静态的,用户不能控制增长行为的方式和时机。第一种则是使用关联的方法,即将一个类的对象嵌入到另外一个对象中,由另外一个对象来决定是否调用嵌入对象的行为以便扩展本身的行为。spa

装饰模式优缺点

装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会以为对象在装饰前和装饰后有什么不一样。装饰模式能够在不须要建立更多子类的状况下,将对象的功能加以扩展。设计

优势
  1. 装饰模式与继承关系的目的都是扩展对象的功能,可是装饰模式能够提供比继承更多的灵活性。
  2. 能够经过一种动态的方式来扩展一个对象的功能,经过配置文件能够在运行时选择不一样的装饰器,从而实现不一样的行为。
  3. 经过使用不一样的具体装饰类以及这些装饰类的排列组合,能够创造出不少不一样的行为的组合。能够使用多个具体装饰类来装饰同一个对象,获得功能更为强大的对象。
  4. 具体构建类与具体装饰类能够独立变化,用户能够根据须要增长新的具体构建类和具体装饰类,在使用其进行组合,原有代码无需改变
缺点
  1. 是以哦那个装饰模式进行系统设计时将产生不少小对象,这些对象的区别在于他们之间的相互链接的方式有所不一样,而不是他们的类或者属性值有所不一样,同时还会由不少具体的装饰类。这些装饰类和小对象的产生将增长系统的复杂度,加大学习理解的难度。
  2. 这种比继承更加灵活机动平的特性,也同时意味着装饰模式比继承更加易于出错,排错也是蛮困难的,对于屡次装饰的对象,调试时寻找错误可能须要逐级排场,较为繁琐,项目复杂度偏高。

示例

装饰模式的主要角色以下:调试

  1. 部件:声明封装器和被封装的对象的公用接口
  2. 具体部件:类是被封装对象所属的类。它定义了基础行为,但装饰类改变了这些行为
  3. 基础装饰:类拥有一个指向被封装对象的引用成员变量。该变量的类型应当被声明尾通用部件接口这样就能够引用具体的部件接口,这样他就能够引用具体的部件和装饰。
  4. 具体装饰类:定义类可动态添加到部件的额外行为。具体装饰类会重写装饰基类的方法,并在调用父类方法以前或以后进行额外的行为。
  5. 客户端:能够使用多层装饰来封装来装饰部件,只要它能使用通用接口与全部对象交互便可。

类图以下所示:code

image

代码示例:component

// 抽象构件
abstract class Component {
    public abstract operate() : void;
}

// 具体构件
class ConcreteComponent extends Component {
    public operate() : void {
        console.log('do something');
    }
}

// 装饰角色
abstract class Decorator extends Component {
    private component : Component = null;
    constructor(component : Component ) {
        super();
        this.component = component;
    }

    public operate() : void {
        this.component.operate();
    }
}

// 具体装饰者
class ConcreteDecoratorA extends Decorator {
    constructor(component : Component) {
        super(component);
    }

    // 定义本身的修饰方法
    private methodA() : void {
        console.log('methodA修饰');
    }

    // 重写父类方法
    public operate() : void {
        this.methodA();
        super.operate();
    }
}

class ConcreteDecoratorB extends Decorator {
    constructor(component : Component) {
        super(component);
    }

    // 定义本身的修饰方法
    private methodB() : void {
        console.log('methodB修饰');
    }

    // 重写父类方法
    public operate() : void {
        this.methodB();
        super.operate();
    }
}

function main() {
    let component : Component = new ConcreteComponent();
    // 第一次装饰
    component = new ConcreteDecoratorA(component);
    // 第二次装饰
    component = new ConcreteDecoratorB(component);
    // 装饰后运行
    component.operate();
}

main();

总结

装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式能够在不须要创造更多子类的状况下,将对象的功能加以扩展。对象

继承是一种耦合度较大的静态关系,没法在程序运行时动态扩展。在软件开发阶段,关联关系虽然不会比继承关系减小编码量,可是到了软件维护阶段,因为关联关系使系统具备较好的松耦合性,所以使得系统更加容易维护。blog

相关文章
相关标签/搜索