使用装饰者模式代替单纯的继承,更好的实现功能的扩展
使用场景
装饰模式应该算是对继承的一种补充,如果单纯的依靠继承扩展类的功能,有时会增加很多子类和继承的层级。
类图
@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的功能