一、装饰者模式
1.1 定义
装饰者模式又名包装(Wrapper)模式
。它可以在不改变原类文件以及不使用继承的情况下,动态地将责任附加到对象上,从而实现动态拓展对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
1.2 遵循的设计原则
-
多用组合,少用继承
继承是编译时静态决定的,所有的子类都会继承到相同的行为。如果能利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
-
开放-关闭原则:类应该对扩展开放,对修改关闭
1.3 和继承相比
- 拓展性好,更加灵活
- 降低了类与类之间的关系
- 如果过度使用,可能会出现很多小类,使程序变得复杂
二、装饰者模式类图
![](https://i-blog.csdnimg.cn/blog_migrate/fdb279b6b364f698dd96ce797112b40c.jpeg)
- 抽象构件
Component
:通常是一个抽象类或者接口,以规范准备接收附加责任的对象。比如说,如果Component
代表人,即使通过装饰也不会使人变成别的动物。 - 具体构件
ConcreteComponent
:定义一个将要接收附加责任的类,是Component
的子类,充当了“被装饰者”的角色。 - 抽象装饰
Decorator
:也是Component
的子类,持有一个抽象构件Component
对象的实例,并定义了与抽象构件中接口一致的接口。 - 具体装饰
ConcreteDecorator
:是Decorator
的子类,作为具体的装饰者,负责给构件对象“贴上”附加的责任。
通常,在
Decorator
或ConcreteDecorator
中,我们会用一个实例变量来保存某个Component
的引用,这样做的目的是获取被装饰者的状态信息,以便将自身的特性加以组合。
三、context继承关系类图(简化版)
![](https://i-blog.csdnimg.cn/blog_migrate/5c7f1fd04bde8f76d6c1c7246c8fe5b8.jpeg)
- Context类:这是一个由
Android系统
提供其实现的抽象类,它是提供应用环境信息的接口。通过它可以访问到应用的资源和类,以及进行一些系统级别的操作,比如加载activity
、发送广播
和接收intent
等。 - ContextImpl类:是
Context
的具体实现类。它只允许android.app
包中的类可以调用它,或者只有和它同包的类才可以通过其父类的方法使用它。它为Activity
、Service
等应用组件提供基本的context对象
。 - ContextWrapper类:是
Context
的一个包装类,其里面所有的方法实现都是调用其内部mBase
变量的方法,而mBase
就是ContextImpl
对象。 - ContextThemeWrapper类:该类允许我们去修改或者替换包装的
context
的主题。
四、Context使用装饰者模式都实现了什么
这部分的内容主要从源码的角度来看装饰者模式在Android Context
中的应用。
Context类族中各类在装饰者模式中的对应关系:
Context类族中 | 装饰者模式中 | 说明 |
---|---|---|
Context | Component | 抽象构件 |
ContextImpl | ConcreteComponent | Context 的具体实现类 |
ContextWrapper | Decorator | 装饰者的父类(其中的所有方法都只是调用了 ContextImpl 中对应的方法) |
ContextThemeWrapper | ConcreteDecorator | 继承自 ContextWrapper 的装饰者 |
Activity | ConcreteDecorator | 继承自 ContextThemeWrapper 的装饰者 |
以常用的startActivity
方法为例,看看装饰者模式在其中的具体实现方式。
Activity
、Application
、Service
的创建都是在ActivityThread
中完成的。
class ContextImpl extends Context {
//启动 Activity 的逻辑实现
@Override
public void startActivity(Intent intent) {
warnIfCallingFromSystemProcess();
startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
// 省略部分代码
// 调用 Instrumentation.execStartActivity() 方法
mMainThread