装饰者模式

Posted zhchoutai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰者模式相关的知识,希望对你有一定的参考价值。

装饰者模式

标签 : Java与设计模式


装饰者模式(Decorator): 又称包装器(Wrapper), 能够动态地为一个对象加入一些额外的职责. 就添加功能来说, 装饰者模式是一种用于替代继承的技术, 他无须通过添加子类继承就能扩展对象的已有功能, 而是使用对象的关联关系取代继承关系 , 更加灵活, 同一时候还可避免类型体系的高速膨胀.

  • 模式组件:
组件 描写叙述 I/O演示样例
Component 抽象构件角色, 真实对象和装饰对象的共同拥有接口. 这样,client就能以调用真实对象的相同方式装饰对象交互. InputStream/OutputStream
ConcreteComponent 详细构件角色,真实对象 FileInputStream/FileOutputStream
Decorator 装饰抽象类, 实现了Component, 并持有一个Component引用, 接受全部client请求,并将请求转发给真实对象, 这样,就能在真实对象调用的前后增强新功能. 但对于Component来说, 是无需知道Decorator存在的. FilterInputStream/FilterOutputStream
ConcreteDecorator 详细装饰角色,完毕对Component的详细增强. BufferedInputStream/BufferedOutputStream

是你还有你, 一切拜托你.(图片来源: 《JAVA与模式》之装饰模式)


实现

  • Component
/**
 * @author jifang
 * @since 16/8/20 下午5:55.
 */
public interface Component {

    void operator();
}

class ConcreteComponent implements Component {

    @Override
    public void operator() {
        System.out.println("详细对象" + this.toString() + "的操作");
    }
}
  • Decorator
public abstract class Decorator implements Component {

    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public abstract void operator();
}

class BeforeAdviceDecorator extends Decorator {

    public BeforeAdviceDecorator(Component component) {
        super(component);
    }

    @Override
    public void operator() {
        System.out.println(" -> 前置增强");
        this.component.operator();
    }
}

class AfterAdviceDecorator extends Decorator {

    public AfterAdviceDecorator(Component component) {
        super(component);
    }

    @Override
    public void operator() {
        this.component.operator();

        System.out.println("后置增强 -> ");
    }
}
  • Client
public class Client {

    @Test
    public void client() {

        // 裸Component
        Component component = new ConcreteComponent();
        component.operator();


        // 前置增强
        component = new BeforeAdviceDecorator(component);
        component.operator();

        // + 后置增强
        component = new AfterAdviceDecorator(component);
        component.operator();
    }
}

注: 假设仅仅有ConcreteComponent而没有抽象的Component, 那么Decorator可直接继承ConcreteComponent. 相同, 假设仅仅有一个ConcreteDecorator, 那就没有必要建立一个独立的Decorator, 将DecoratorConcreteDecorator的职责合并.


小结

  • 装饰者模式是为已有功能动态加入很多其它功能的一种方式: 把类内装饰逻辑从类中剥离, 以简化原有类设计:
    • 有效地将类的核心职责和装饰功能区分开;
    • 去除相关类中反复的装饰逻辑;
    • 能够对一个对象装饰多次, 构造出不同行为的组合, 得到功能更强大的对象;
    • 详细构件类和详细装饰类可独立变化, 且用户可依据须要添加新的详细构件子类详细装饰子类.
  • 与桥接模式的对照
    两个模式都是为了解决子类过多问题, 但他们的诱因不同:
    • 桥接模式对象自身有沿着多个维度变化的趋势, 本身不稳定;
    • 装饰者模式对象自身很稳定, 仅仅是为了添加新功能/增强原功能.
  • 与适配器模式的不同
    装饰者与适配器都有一个别名:包装模式(Wrapper), 它们看似都是起到包装一个接口/类/对象的作用, 但包装形式却不同.

    • 适配器的意义是将一个接口转变成还有一个接口: 通过改变接口达到反复使用的目的;
    • 而装饰者不改变被装饰对象的接口, 而恰恰保持了原有的接口: 增强原有对象的功能, 或改变原有对象的处理方法而提升性能.
  • 继承、装饰者模式、动态代理对照

* 继承 装饰者 动态代理
对象 被增强对象不能变 被增强对象可变 被增强对象可变
内容 增强内容不能变 增强内容不可变 增强内容可变
  • 常见场景
    当系统更新、原有逻辑须要增强时, 我们最初的想法是 向旧的类中加入新代码, 由新代码装饰原有类的主要行为, 他们会在主类中加入新的字段/方法/逻辑, 但相同也添加了主类的复杂度, 而这些新加入的内容仅仅是为了满足一些仅仅在某种特定情况下才会运行的特殊行为的须要. 而装饰者模式提供了一个解决该问题的很好的方案: 把每一个要装饰的功能放在单独的类中, 并让这个类包装它所要装饰的对象, 当须要运行特殊行为时, 客户代码就能够在运行时依据须要有选择地、按顺序地使用装饰过的包装对象了, 如:

參考:
设计模式: 可复用面向对象软件的基础
大话设计模式
高淇讲设计模式
深入分析Java Web技术内幕(修订版)
装饰模式与适配器模式的的差别


以上是关于装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式之装饰者模式

设计模式整理_装饰者模式

设计模式-装饰者模式(Go语言描述)

设计模式-装饰者模式(Go语言描述)

装饰者模式

设计模式 之 装饰者模式