装饰器模式
装饰器模式又称为包装模式。通常给对象添加功能,要么直接修改对象添加相应的功能,要么派生子类来扩展,或是使用对象组合的方式。显然,直接修改对应的类的方式并不可取,在面向对象的设计中,我们应该尽量使用组合对象而不是继承对象来扩展和复用功能,装饰器模式就是基于对象组合的
方式的。装饰器模式以对用户透明的方式动态的给一个对象附加上了更多的责任。
装饰器模式涉及的角色
1.抽象构件角色
给出一个抽象接口,以规范准备接受附加责任的对象
2.具体构件角色
定义一个将要接受附加责任的累
3.装饰角色
持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口
4.具体装饰角色
负责给构件对象贴上附加的责任
装饰器模式实例
组件对象的接口(需要装饰的抽象)
1 public abstract class Component { 2 /** 3 * 示例方法 4 */ 5 public abstract void operation(); 6 }
组件对象具体的实现
1 public class ConcreteComponent extends Component { 2 3 public void operation() { 4 //相应的功能处理 5 } 6 7 }
装饰器接口
1 public abstract class Decorator extends Component { 2 /** 3 * 持有组件对象 4 */ 5 protected Component component; 6 7 /** 8 * 构造方法,传入组件对象 9 * @param component 组件对象 10 */ 11 public Decorator(Component component) { 12 this.component = component; 13 } 14 15 public void operation() { 16 //转发请求给组件对象,可以在转发前后执行一些附加动作 17 component.operation(); 18 } 19 20 21 }
装饰器实现
1 public class ConcreteDecoratorA extends Decorator { 2 public ConcreteDecoratorA(Component component) { 3 super(component); 4 } 5 private void operationFirst(){ } //在调用父类的operation方法之前需要执行的操作 6 private void operationLast(){ } //在调用父类的operation方法之后需要执行的操作 7 public void operation() { 8 //调用父类的方法,可以在调用前后执行一些附加动作 9 operationFirst(); //添加的功能 10 super.operation(); //这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能 11 operationLast(); //添加的功能 12 } 13 }
main
1 public class Client{ 2 public static void main(String[] args){ 3 Component c1 = new ConcreteComponent (); //首先创建需要被装饰的原始对象(即要被装饰的对象) 4 Decorator decoratorA = new ConcreteDecoratorA(c1); //给对象透明的增加功能A并调用 5 decoratorA .operation(); 6 Decorator decoratorB = new ConcreteDecoratorB(c1); //给对象透明的增加功能B并调用 7 decoratorB .operation(); 8 Decorator decoratorBandA = new ConcreteDecoratorB(decoratorA);//装饰器也可以装饰具体的装饰对象,此时相当于给对象在增加A的功能基础上在添加功能B 9 decoratorBandA.operation(); 10 } 11 }
使用场景
1.需要在不影响其他对象的情况下,以动态透明的方式给对象添加职责。
2.如果不适合使用子类进行扩展时,可以使用装饰器模式。
装饰器模式和代理模式看起来很像。对装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个 接口。对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。然而,实际上,在装饰器模式和代理模式之间还是有很多差别的。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。