一句话总结:
装饰器模式就像「给手机装保护壳」—— 不拆原机,动态增强功能,Android 里的 ContextWrapper、Java IO流 都靠它灵活升级!
一、装饰器模式在 Android 的经典案例
核心思想:通过包装(Wrapper) 动态扩展对象功能,不修改原类代码,避免继承导致的类爆炸。
1. Context 体系的装饰器结构
// 组件接口:Context(被装饰对象的抽象)
public abstract class Context {
public abstract void startActivity(Intent intent);
public abstract Object getSystemService(String name);
}
// 具体组件:ContextImpl(实际干活的小弟)
class ContextImpl extends Context {
@Override
public void startActivity(Intent intent) {
// 真正启动 Activity 的逻辑(通过 AMS)
}
}
// 装饰器基类:ContextWrapper(持有一个 Context 引用)
public class ContextWrapper extends Context {
protected Context mBase; // 被装饰对象
public ContextWrapper(Context base) {
mBase = base;
}
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent); // 委托给实际 Context
}
}
// 具体装饰器:ContextThemeWrapper(增加主题功能)
public class ContextThemeWrapper extends ContextWrapper {
private Resources.Theme mTheme;
@Override
public void setTheme(int resid) {
mTheme = resources.newTheme(); // 添加主题处理逻辑
}
}
// 最终使用:Activity 继承自 ContextThemeWrapper
public class Activity extends ContextThemeWrapper {
// Activity 本身也是一个装饰器!
}
装饰链:
ContextImpl → ContextWrapper → ContextThemeWrapper → Activity
每层装饰添加新功能(如主题、生命周期管理),层层增强!
二、源码级工作原理分析
1. 创建 Activity 时的装饰过程
当启动 Activity 时,系统通过以下步骤构建 Context 装饰链:
// 创建 ContextImpl(具体组件)
ContextImpl contextImpl = new ContextImpl(...);
// 用 ContextWrapper 包装
ContextWrapper contextWrapper = new ContextWrapper(contextImpl);
// 继续用 ContextThemeWrapper 装饰
ContextThemeWrapper themeWrapper = new ContextThemeWrapper(contextWrapper);
// 最终 Activity 持有装饰后的 Context
class MainActivity extends Activity {
// 实际使用的是被多层装饰后的 Context
}
2. 方法调用流程(以 startActivity 为例)
Activity.startActivity() →
ContextThemeWrapper.startActivity() →
ContextWrapper.startActivity() →
ContextImpl.startActivity()
- 透明增强:Activity 无需知道底层如何启动,只管调用
- 功能扩展:中间层可插入额外逻辑(如权限检查)
三、装饰器 vs 继承 vs 代理模式
| 维度 | 装饰器模式 | 继承 | 代理模式 |
|---|---|---|---|
| 核心目标 | 动态增强功能 | 静态扩展功能 | 控制对象访问 |
| 关系 | 组合 + 相同接口 | 父子类关系 | 相同接口 |
| 灵活性 | 高(运行时动态组合) | 低(编译时确定) | 中 |
| Android案例 | ContextWrapper → ContextImpl | 自定义 View 继承系统 View | ActivityManagerProxy |
四、装饰器模式的优缺点
优点:
- 灵活扩展:动态添加功能,无需修改原类(如给 Context 加主题)
- 避免类爆炸:替代多层次的继承(如
ContextWrapper仅 600 行代码,支撑整个 Activity 体系) - 符合开闭原则:扩展开放,修改关闭
缺点:
- 多层装饰难调试:调用链过长时定位问题困难
- 设计复杂度高:需设计大量小类(如
ContextThemeWrapper、TintContextWrapper)
五、实际开发场景建议
适用场景:
- 动态增强系统类功能(如给
InputStream加缓冲) - 避免污染原有代码(如第三方 SDK 的功能扩展)
- 组合替代继承(如 UI 组件功能定制)
不适用场景:
- 功能变化少:直接继承更简单
- 需要彻底重写方法:装饰器模式不适合完全改变行为
六、总结口诀
「装饰模式像套娃,层层包装功能加
Context 体系是典范,Java IO 也靠它
若要扩展不改码,组合替代继承法」