一句话说透Android里面的适配器模式、装饰者模式、外观模式的区别

217 阅读4分钟

一句话总结:
适配器模式是「转接头」,装饰者模式是「套娃增强」,外观模式是「酒店前台」—— 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 复用机制)

使用场景

  • 列表数据展示(ListViewRecyclerView
  • 类型转换(如将 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 交互
  • 整合了 WindowManagerLayoutInflater 等复杂模块

使用场景

  • 启动四大组件
  • 获取系统服务(如 getSystemService()

特点

  • 简化调用流程
  • 不改变子系统结构,只提供统一入口

四、三种模式对比表

维度适配器模式装饰者模式外观模式
核心目标解决接口不兼容动态增强功能简化复杂系统调用入口
关系特点适配器与被适配类接口不同装饰者与被装饰类接口相同外观类与子系统类接口不同
交互方向单向适配(数据→视图)单向包裹(功能叠加)单向代理(用户→子系统)
Android案例RecyclerView.AdapterContextWrapper → ContextContext 封装系统服务
性能影响高频数据绑定需优化多层嵌套可能影响调用链性能几乎无额外开销

五、源码级原理剖析

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();  
    }  
}  
  • 统一入口:用户无需关心 EngineDiskCache 等底层模块

六、使用场景口诀

接口不兼容找适配,动态增强用装饰
系统复杂入口多,外观模式一把收

实际开发选择指南

  1. 列表数据展示 → 适配器模式(必须的!)
  2. 逐步扩展功能(如加密 + 压缩流) → 装饰者模式
  3. SDK 设计或封装复杂模块 → 外观模式

注意事项

  1. 避免在适配器中写业务逻辑(仅做数据转换)
  2. 装饰者模式嵌套不宜超过 3 层(否则调试困难)
  3. 外观类不要变成“上帝类”(保持单一职责)

七、逆向思维:如何快速区分?

  • 适配器模式:总能看到 Adapter 结尾的类,代码中有 convertView 和 ViewHolder
  • 装饰者模式:类的构造函数中传入同类对象(如 new BufferedInputStream(fileStream)
  • 外观模式:一个简单方法背后调用了多个子系统(如 context.startActivity() 触发权限校验、生命周期管理等)

经典误用案例
在自定义 View 中既做数据适配(适配器)又添加阴影效果(装饰者),导致代码混乱——应该拆分成 Adapter + 自定义装饰 View


总结口诀
适配转接口,装饰包功能,外观简入口
列表必用适配器,流式处理上装饰,封装服务靠外观