目的:动态地给一个对象添加一些额外的职责。一般我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下扩展类。将具体功能职责划分,同时继承装饰者模式。
使用场景:
(1)需要在不影响其他对象的情况下,以动态、透明的方式给对象添加职责。
(2)如果不适合使用子类来进行扩展的时候,可以考虑使用装饰器模式。
具体例子:
(1)组件对象的接口,可以给这些对象动态的添加职责 public abstract class Component { /** * 示例方法 */ public abstract void operation(); } (2)具体实现组件对象接口的对象 public class ConcreteComponent extends Component { public void operation() { //相应的功能处理 } } (3)装饰器接口,维持一个指向组件对象的接口对象, 并定义一个与组件接口一致的接口 public abstract class Decorator extends Component { /** * 持有组件对象 */ protected Component component; /** * 构造方法,传入组件对象 * @param component 组件对象 */ public Decorator(Component component) { this.component = component; } public void operation() { //转发请求给组件对象,可以在转发前后执行一些附加动作 component.operation(); } } (4)装饰器的具体实现对象,向组件对象添加职责,operationFirst(),operationLast()为前后需要添加的功能。具体的装饰器类ConcreteDecoratorB代码相似,不在给出。 public class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component component) { super(component); } private void operationFirst(){ } //在调用父类的operation方法之前需要执行的操作 private void operationLast(){ } //在调用父类的operation方法之后需要执行的操作 public void operation() { //调用父类的方法,可以在调用前后执行一些附加动作 operationFirst(); //添加的功能 super.operation(); //这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能 operationLast(); //添加的功能 } } (5) 客户端使用装饰器的代码 public class Client{ public static void main(String[] args){ Component c1 = new ConcreteComponent (); //首先创建需要被装饰的原始对象(即要被装饰的对象) Decorator decoratorA = new ConcreteDecoratorA(c1); //给对象透明的增加功能A并调用 decoratorA .operation(); Decorator decoratorB = new ConcreteDecoratorB(c1); //给对象透明的增加功能B并调用 decoratorB .operation(); Decorator decoratorBandA = new ConcreteDecoratorB(decoratorA);//装饰器也可以装饰具体的装饰对象,此时相当于给对象在增加A的功能基础上在添加功能B decoratorBandA.operation(); } }
经典例子:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); //其中file为某个具体文件的File或者FileDescription对象
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,就可以提供一个内存缓冲区来保存从文件中读取的输入流。