装饰器模式(Decorator Pattern)

来源:互联网 发布:淘宝找相似 编辑:程序博客网 时间:2024/05/29 09:13

参考文章:

http://blog.csdn.net/hust_is_lcd/article/details/7884320

http://blog.csdn.net/hguisu/article/details/7531960


定义:

    是指对一个类的功能进行扩展,同时保证不修改原类的代码。(遵循开闭原则)


解决的问题:


  • 需要动态地扩展一个类的功能时,非常灵活,可增可消。(注意,继承只能静态地扩展,无法消去)。
  • 装饰模式用于弥补类继承模式无法遵循里氏代换原则的不足。


模式组成:

抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,

即可以给这些对象动态地添加职责。

具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。

可以给这个类的对象添加一些职责

抽象装饰器(Decorator):维持一个指向构件Component对象的实例,

并定义一个与抽象组件角色Component接口一致的接口

具体装饰器角色(ConcreteDecorator):向组件添加职责。


uml类图:





优点:


  • 动态的扩展一个类的功能,可增加可删除。(继承只能增加功能,无法删除)
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
  • 弥补类继承模式无法遵循里氏代换原则的不足。
  • 避免在层次结构高层的类有太多的特征 。Decorator模式提供了一种“即用即付”的方法来添加职责


应用场景:


  • 需要在不影响其他对象的情况下,以动态、透明的方式给对象添加职责
  • 如果不适合使用子类来进行扩展的时候,可以考虑使用装饰器模式


Java中的IO是明显的装饰器模式的运用。FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于Component,是其他组件类的父类,也是Decorator类的父类)。继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于ConcreteComponent类。而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即ConcreteDecorator类。通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据。我们使用如下的代码来使用BufferedInputStream装饰FileInputStream,就可以提供一个内存缓冲区来保存从文件中读取的输入

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); //其中file为某个具体文件的File或者FileDescription对象 

装饰器模式vs代理模式:


相同点:实现基本相同

区别:

  • 代理模式中,代理类对被代理的对象有控制权,决定其执行或者不执行。
  • 装饰模式中,装饰类对代理对象没有控制权,只能为其增加一层装饰,以加强被装饰对象的功能,仅此而已。



举个栗子:


定义抽象角色

abstract class Food {public abstract String getDesc();}

定义抽象装饰器

abstract class FoodDecoration extends Food {@Overridepublic abstract String getDesc();}

定义具体角色

class Duck extends Food {@Overridepublic String getDesc() {return "鸭肉";}}
定义具体装饰器
class RoastFood extends FoodDecoration {private Food food;public RoastFood(Food f) {this.food = f;}@Overridepublic String getDesc() {return getDecoration() + food.getDesc();}private String getDecoration() {return "烤";}}
定义具体装饰器
class SteamedFood extends FoodDecoration {private Food food;public SteamedFood(Food f) {this.food = f;}@Overridepublic String getDesc() {return getDecoration() + food.getDesc();}private String getDecoration() {return "蒸";}}

输出结果:

可以对同一个角色增加多个装饰器修饰