装饰模式

介绍

装饰模式(Decorator Pattern) 也称为包装模式(Wrapper Pattern),结构型设计模式之一,其使用一种对客户端透明的方式来动态地扩展对象的功能,同时它也是继承关系的一种代替方案之一。

定义

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活。

使用场景

需要透明且动态地扩展类的功能时

角色介绍

  • Component 抽象组件,可以是一个接口或者抽象类,其充当的就是被装饰的原始对象
  • ConcreteComponent 组件具体实现类,也是我们装饰的具体对象
  • Decorator 抽象装饰者,其承担的职责就是为了装饰我们的组件对象,其内部一定要有一个指向组件对象的引用。大多数情况下,该类为抽象类,需要根据不同的装饰逻辑实现不同的具体子类。当然,如果装饰逻辑单一,只有一个的情况我们可以省略该类直接作为具体的装饰者。
  • ConcreteDecorator 装饰者具体实现类,只是对抽象装饰者做出具体实现。
  • Client 客户类,创建组件实现类的对象,根据组件对象构造装饰者对象,调用装饰者对象的方法执行任务

抽象的装饰者中持有一个组件实现类的对象的引用,并且抽象的装饰者要继承抽象的组件。在抽象装饰者对组件抽象方法的实现过程中,调用组件实现类的引用的对应方法。在装饰者的实现类中,重写从父类继承的抽象组件的方法,在 super.operate() 前后可以添加需要插入的装饰代码。

抽象装饰者中保持对组件类对象的引用,可以方便地调用具体被装饰对象中的方法,我们就可以在不破坏原类层次结构的情况下为类增加一些功能,我们只需要在被装饰对象的想应方法前或后添加相应逻辑即可。

Android 源码中的装饰模式

Context 在 Android 中被称为“上帝对象”,它是一个抽象类,对应的有 ContextWrapper,ContextImpl,Activity,Service,Application

Context 对应抽象模式中的抽象组件,ContextImpl 继承了 Context,对应装饰模式中的组件实现类。

ContextWrapper 继承了 Context,对应装饰模式中的装饰类对象,其保持了一个对 ContextImpl 的引用。

Activity、Service,Application 继承了 ContextWrapper ,对应装模式中的具体装饰者

装饰模式和代理模式区别

  1. 装饰模式和我们前面的代理模式有点类似,有时容易混淆,经常将装饰模式看作代理。

  2. 装饰模式是对客户端透明的方式扩展对象的功能,是继承的一个代替方案

  3. 而代理模式则是给对象提供一个代理,并有代理对象来控制对原有对象的引用

  4. 装饰模式应该为所装饰的对象增强功能

  5. 代理模式是对代理的对象施加控制,但不对对象本身功能进行增强

推荐阅读更多精彩内容