This page looks best with JavaScript enabled

装饰者模式

 ·  ☕ 2 min read

使用装饰者模式代替单纯的继承,更好的实现功能的扩展

使用场景

装饰模式应该算是对继承的一种补充,如果单纯的依靠继承扩展类的功能,有时会增加很多子类和继承的层级。

类图

@startuml

interface Component{
+ operation()
}

class ConcreteComponent{
+ operation()
}

abstract class Decoration{
 - Component component
}

Component <|.. ConcreteComponent
Component <|.. Decoration

Decoration o-- Component

class ConcreteDecoration extends Decoration {
+ operation()
}

@enduml

@enduml
  • Component 抽象组件,一个接口或抽象类

  • ConcreteComponent 一个具体的组件,实现了 Component 抽象组件

  • Decoration 装饰角色,是一个抽象类,其中必定有一个私有属性引用 Component 对象

  • ConcreteDecoration 一个具体的装饰者

实例

Android SDK 中的 Context

@startuml

abstract class Context

class ContextImpl extends Context

class ContextWrapper extends Context{
+ Context mBase;
}

class ContextThemeWrapper extends ContextWrapper{
}

ContextImpl -o ContextWrapper

class Application extends ContextWrapper

class Service extends ContextWrapper

class Activity extends ContextThemeWrapper

@enduml

在 Android 中,Context 意为上下文,是一个应用的环境信息接口。Android 中 Activity Service Application 都间接的继承自 Context。

Context 是一个抽象类,内部定义了很多方法和静态常量,它的实现类是 ContextImpl。

ContextImpl 和 ContextWrapper 继承自 Context,ContextWrapper 内部包含 Context 类型的 mBase 对象,mBase 具体指向 ContextImpl,ContextImpl 提供了很多功能,但是外界需要使用并扩展 ContextImpl 的功能,因此设计上使用了装饰模式,ContextWrapper 是装饰类,它对 ContextImpl 进行包装,ContextWrapper 主要起了方法传递的作用,ContextWrapper 中几乎所有方法都是通过调用 mBase 对象引用的 ContextImpl 的相应方法。

这里使用装饰模式有以下优点:

  • 使用者能更方便的使用 Context
  • 如果 ContextImpl 发生了改变,ContextWrapper 也不用修改
  • ContextImpl 的实现不会暴露给使用者
  • 通过组合而非继承的方式扩展 ContextImpl 的功能
Support the author with
alipay QR Code
wechat QR Code

Yang
WRITTEN BY
Yang
Developer