一句话总结:
适配器模式是「转接头」,装饰者模式是「套娃增强」,外观模式是「酒店前台」—— Android 系统里各司其职,一个解决兼容,一个动态升级,一个简化入口!
一、适配器模式(Adapter)—— 万能转接头
核心:接口转换,让不兼容的类协同工作
Android 源码例子:RecyclerView.Adapter
// RecyclerView.Adapter 将数据适配成 View
public abstract class Adapter<VH extends ViewHolder> {
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
public abstract void onBindViewHolder(VH holder, int position);
}
// 自定义 Adapter(数据 → View 的转换)
class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private List<String> mData;
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.textView.setText(mData.get(position)); // 数据绑定到 View
}
}
底层原理:
- 通过
Adapter将数据源(如List)和RecyclerView的解耦 - 复用
ViewHolder避免频繁创建 View(convertView复用机制)
使用场景:
- 列表数据展示(
ListView、RecyclerView) - 类型转换(如将
Cursor数据转为 Java 对象)
特点:
- 解决接口不匹配
- 通常持有被适配对象的引用
二、装饰者模式(Decorator)—— 俄罗斯套娃
核心:动态扩展功能,层层包裹增强能力
Android 源码例子:ContextWrapper 对 Context 的包装
// ContextWrapper 装饰 Context
public class ContextWrapper extends Context {
Context mBase; // 被装饰对象
public ContextWrapper(Context base) {
mBase = base;
}
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent); // 委托给实际 Context 执行
}
}
// Activity 继承自 ContextThemeWrapper(装饰链)
// ContextImpl → ContextWrapper → ContextThemeWrapper → Activity
底层原理:
- 每层装饰类添加新功能(如
ContextThemeWrapper增加主题支持) - 通过组合而非继承扩展功能
使用场景:
- 动态添加功能(如加密流、缓存处理)
- 系统服务的包装(如
Service封装ContextImpl)
特点:
- 透明增强(使用者无感知)
- 装饰类和被装饰类实现相同接口
三、外观模式(Facade)—— 酒店前台
核心:统一入口简化操作,隐藏子系统复杂性
Android 源码例子:Context 类
// Context 封装所有系统服务入口
public abstract class Context {
public abstract void startActivity(Intent intent);
public abstract Object getSystemService(String name);
public abstract Resources getResources();
}
// 实际实现类 ContextImpl(处理复杂逻辑)
class ContextImpl extends Context {
@Override
public void startActivity(Intent intent) {
// 内部调用 ActivityTaskManagerService、PackageManager 等子系统
mMainThread.getActivityTaskManager().startActivity(...);
}
}
底层原理:
- 用户调用
context.startActivity()无需关心底层如何与ActivityTaskManagerService交互 - 整合了
WindowManager、LayoutInflater等复杂模块
使用场景:
- 启动四大组件
- 获取系统服务(如
getSystemService())
特点:
- 简化调用流程
- 不改变子系统结构,只提供统一入口
四、三种模式对比表
| 维度 | 适配器模式 | 装饰者模式 | 外观模式 |
|---|---|---|---|
| 核心目标 | 解决接口不兼容 | 动态增强功能 | 简化复杂系统调用入口 |
| 关系特点 | 适配器与被适配类接口不同 | 装饰者与被装饰类接口相同 | 外观类与子系统类接口不同 |
| 交互方向 | 单向适配(数据→视图) | 单向包裹(功能叠加) | 单向代理(用户→子系统) |
| Android案例 | RecyclerView.Adapter | ContextWrapper → Context | Context 封装系统服务 |
| 性能影响 | 高频数据绑定需优化 | 多层嵌套可能影响调用链性能 | 几乎无额外开销 |
五、源码级原理剖析
1. 适配器模式在 ListView 中的实现
// frameworks/base/core/java/android/widget/BaseAdapter.java
public abstract class BaseAdapter implements ListAdapter {
public abstract View getView(int position, View convertView, ViewGroup parent);
// 数据源与 View 的转换
public Object getItem(int position) { return null; }
}
// ArrayAdapter 源码(简化)
public class ArrayAdapter<T> extends BaseAdapter {
private List<T> mObjects;
@Override
public View getView(...) {
TextView textView = (TextView) convertView.findViewById(R.id.text);
textView.setText(mObjects.get(position));
return convertView;
}
}
- 复用机制:
convertView复用减少 View 创建开销
2. 装饰者模式在 Java IO 流中的应用
// frameworks/base/core/java/java/io/InputStream.java
public class BufferedInputStream extends FilterInputStream {
protected volatile InputStream in;
public BufferedInputStream(InputStream in) {
super(in); // 装饰原始流
}
@Override
public int read() throws IOException {
// 添加缓冲功能
if (pos >= count) fillBuffer();
return buf[pos++] & 0xff;
}
}
- 功能叠加:通过嵌套装饰类实现流的功能扩展
3. 外观模式在 Glide 中的应用
// Glide 外观类封装复杂图片加载逻辑
public class Glide {
public static RequestManager with(Activity activity) {
return getRetriever(activity).get(activity);
}
private static RequestManagerRetriever getRetriever(Context context) {
// 内部初始化线程池、缓存、解码器等模块
return Glide.get(context).getRequestManagerRetriever();
}
}
- 统一入口:用户无需关心
Engine、DiskCache等底层模块
六、使用场景口诀
「接口不兼容找适配,动态增强用装饰
系统复杂入口多,外观模式一把收
实际开发选择指南:
- 列表数据展示 → 适配器模式(必须的!)
- 逐步扩展功能(如加密 + 压缩流) → 装饰者模式
- SDK 设计或封装复杂模块 → 外观模式
注意事项:
- 避免在适配器中写业务逻辑(仅做数据转换)
- 装饰者模式嵌套不宜超过 3 层(否则调试困难)
- 外观类不要变成“上帝类”(保持单一职责)
七、逆向思维:如何快速区分?
- 适配器模式:总能看到
Adapter结尾的类,代码中有convertView和ViewHolder - 装饰者模式:类的构造函数中传入同类对象(如
new BufferedInputStream(fileStream)) - 外观模式:一个简单方法背后调用了多个子系统(如
context.startActivity()触发权限校验、生命周期管理等)
经典误用案例:
在自定义 View 中既做数据适配(适配器)又添加阴影效果(装饰者),导致代码混乱——应该拆分成 Adapter + 自定义装饰 View
总结口诀:
「适配转接口,装饰包功能,外观简入口
列表必用适配器,流式处理上装饰,封装服务靠外观」