装饰模式

                                                 装饰模式

  摘要:装饰模式:Decorator模式(别名Wrapper),动态地给对象添加一些额外的职责。从功能上来说,装饰模式比生成子类更为灵活。

  装饰模式的结构

  装饰模式的结构包括4种角色:

  1.抽象组件(Component):抽象组件(抽象类或接口)定义了需要进行装饰的方法,简单来说如果一个类继承自该类或实现了该类就具有了装饰或被装饰的能力。

  2.具体组件(ConcreteComponent):具体组件是抽象组件的子类,是“被装饰者”角色。

  3.装饰者(Decorator):装饰者是抽象组件的一个子类,是“装饰者”角色,其作用是装饰具体组件,需要包含Component的引用。装饰者可以是抽象类,也可以是非抽象类。

  4.具体装饰(ConcreteDecorator):具体装饰是装饰者的一个非抽象子类。

  装饰模式的UML类图如下图所示:

  

  Component:

  定义一个接口(或抽象类)

public interface Component{
    public abstract void operation();
  }

  ConcreteComponent:

  具体组件(被装饰者)

public class ConcreteComponent implenents Component{
    public void operation(){
        ......
    }
}

  Decorator:

  装饰者(其实就是一个装饰器,通过包装一个具体组件来扩展其功能,而不是通过改变原有接口来扩展功能

        这里怎样看出是包装了一个具体组件呢?

      Decorator类中有以Component为参数的构造函数,而ConcreateDecorator继承了Decorator的并调用了父类的构造方法,当实例化一个ConcreteDecorator时,肯定要传入一个“component”,而这个“component”,其实真正传入的是一个ConcreateComponent的实例(因ConcreateComponent实现了Component,多态的体现),所以说装饰器包装的是一个具体组件。

public class Decorator implements Component{
    private Component component;
    public Decorator(Component component)
        {
            this.component=component;
        }
    public void operation(){
        component.operation();
        }
    }

  ConcreteDecorator:

  在被装饰者的行为(super.operation())之前或之后,加上自己的行为,以完成附加的职责。 

public class ConcreteDecorator extends Decorator{
    private Component component;//拥有一个指向Component的引用
    public ConcreteDecorator(Component component){//利用构造函数初始化component
        super(component);//调用父类的构造方法
        }
        public void operation(){
            super.operation();//调用父类的operation()方法
            addBehaviour();//也可以在super.operation前面
        }
        private void addBehaviour(){
            ......
        }
}

  设计原则

  1.多用组合,少用继承。

  利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

  2.类应设计的对扩展开放,对关闭修改。

  要明确的重点

  1.装饰者和被装饰者有相同的父类。

  2.可以用一个或多个装饰者装饰一个被装饰者。

  3.装饰者可以在被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的。

  4.对象可以在任何时候被装饰,可以在运行时动态的,不限量的用喜欢的装饰者来装饰对象。

  5.装饰模式中使用继承的关键是想达到装饰者和被装饰对象的类型匹配而不是获取其行为。

  6.适配器模式的用意是改变对象的接口而不一定改变对象的性能,而装饰者模式的用意是保持接口并增加对象的职责

  什么情况下使用装饰模式

  1.需要扩展一个类的功能,或给一个类添加附加职责。

  2.需要动态地给一个对象添加功能,这些功能可以再动态的撤销,而又不影响到该类的其他对象。

  3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

  4.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类的数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

  装饰模式的优点

  1.被装饰者和装饰者是弱耦合关系。由于装饰者(Decorator)仅仅依赖于抽象组件(Component),因此具体装饰只知道它要装饰的对象是抽象组件的某一个子类的实例,但不需要知道是哪一个具体子类。

  2.装饰模式满足“开-闭原则”。不必修改具体组件,就可以增加新的针对该具体组件的具体装饰。

  3.装饰模式与继承关系的目的都是要扩展对象的功能,但装饰模式可以提供比继承更多的灵活性。

  4.通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

  装饰模式的缺点

  1.这种比继承更加灵活的特性,同时带来了复杂性。

  2.装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

  3.装饰模式是针对抽象组件(Component)类型编程。但是,如果要针对具体组件编程时,就应该重新思考应用的架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

  装饰模式在Java IO中的应用

   

  参考了很多资料,(主要参考自:http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html 以及《面向对象与设计模式》耿祥义 张跃平著),刚开始实在是理解不透,经过反复琢磨,感觉稍微理解了一些,绝大部分都是摘抄下来的,图是用Rational Rose画的,彩色字体部分加入了自己的一点点思想和感悟,希望以后在具体项目中可以对装饰模式有更加深刻、透彻的领悟。

  

原文地址:https://www.cnblogs.com/dazuihou/p/3619517.html