装饰者模式

装饰者、装饰器模式,Decorator。在原来的类上进行一些装饰,他们仍然使用相同的接口。不同于Proxy,装饰器需要传入要被装饰的类,然后对其功能进行扩展,所以装饰器模式相比较代理模式耦合性更低。但是代理类在使用时,不用创建被代理类的依赖类。

装饰者模式是一种替代继承的技术,他通过一种无需定义子类的方式给对象动态的增加职责,使用对象之间的关联关系取代对象之间的继承关系。

代码:

// 被装饰者接口
public interface Component {
    public void sampleOpreation();
}
// 被装饰的具体实现
public class ConcreteComponent implements Component {
    @Override
    public void sampleOpreation() {
        // TODO 完成相关的业务代码
    }
}
// 抽象装饰类,核心
public abstract class Decorator implements Component {
   
   // 维持一个对抽象构建对象的引用
   private Component component;
   // 通过构造注入一个抽象构建类型的对象
   public Decorator(Component component) {
       this.component = component;
   }
   
   @Override
   public void sampleOpreation() {
       //委派给被装饰者处理核心
       component.sampleOpreation();
   }

}
// 具体的装饰类,用以具体的装饰
public class ConcreteDecoratorB extends Decorator {
   public ConcreteDecoratorB(Component component) {
      super(component);
   }
    
   @Override
   public void sampleOpreation() {
      //TODO 完成相关的业务代码
      super.sampleOpreation();
      //TODO 完成相关的业务代码
   }
}

具体应用实例,文件加载接口,增加一个加密的装饰:

优缺点

优点:

  1. 比继承更加灵活,不会导致类的个数极具增加

  2. 可以通过动态的方式来扩展一个对象的功能,通过配置文件在运行时选择不同的具体的装饰类,从而实现不同的行为

  3. 可对一个对象进行多次装饰,使用不同的装饰进行排列组合完成更复杂的装饰功能

  4. 具体的装饰类可以独立变化,用户可需要增加新的具体的构建类和具体的装饰类,且原有的代码不用发生变动,符合开闭原则。

缺点:

  1. 使用装饰模式进行系统设计时将产生很多的小对象,这些对象的区别在于他们之间相互连接的方式不同,而不是他们的类或者属性不同,大量的小对象势必会占用更多的系统资源,在一定程度上影响性能

  2. 装饰器模式提供一种比继承更加灵活的解决方案,但是同样意味着他会比继承更容易出错,也会增加拍错困难,对于多次装饰的对象,在调试寻找错误时需要逐级排查,较为繁琐

使用场景

  1. 快速动态的扩展和撤销一个类的功能场景

  2. 不支持通过继承扩展类的场景(类被final修饰,或者类的子类过多,需要对每个子类扩展的时候)。

  3. 装饰Spring容器中的对象,可以在被装饰对象中新增一个方法用以创建一个新的装饰后的对象(定义接口 Decorative,UserService实现该接口,并提供方法 UserServiceDecorator decorated(Class<?> decoratorClass ...))

  4. 优惠券规则叠加,各种类型的优惠券规则可以很随意的进行排列组合(也可以使用责任链模式)

  5. API接口使用装饰者控制对报文进行不同规则的压缩、加密等

  6. InputStream、OutputStream

  7. QueueingFuture 类是对FutureTask类的包装,前者继承了FutureTask类,因为FutureTask类实现了接口RunnableFuture,也就是说他们拥有相同的接口。创建QueueingFuture对象需要在构造提供一个RunnableFuture对象,也就是被包装的对象。

最后更新于