zoukankan      html  css  js  c++  java
  • 装饰者模式

    装饰者模式

    标签 : 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技术内幕(修订版)
    装饰模式与适配器模式的的差别


  • 相关阅读:
    我所认识的JavaScript
    谈如何边做事,边提高
    对JavaScript开发中困扰的思考
    Soundex语音算法
    Perl分割字符串的一个精妙的写法
    Perl深拷贝
    Git diff hash顺序的问题
    perl命令行批量修改文件内容
    IOS写文件
    删除Linux乱码文件
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8371670.html
Copyright © 2011-2022 走看看