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