一句话说透Android里面的装饰模式、代理模式、桥接模式的区别

241 阅读4分钟

一句话总结:
装饰模式是「套娃增强」,代理模式是「中介代购」,桥接模式是「两岸建桥」—— 三种模式形似而神不似,Android 系统里各显神通!


一、装饰模式(Decorator)—— 俄罗斯套娃

核心动态扩展对象功能,层层包裹增强能力
Android 源码例子:Java IO 流在 Android 的应用

// 创建多层装饰的流  
InputStream in = new FileInputStream("test.txt");  
in = new BufferedInputStream(in); // 加缓冲  
in = new GZIPInputStream(in);     // 加解压  

// 底层实现:装饰类继承同一接口  
public class BufferedInputStream extends FilterInputStream {  
    public BufferedInputStream(InputStream in) {  
        super(in); // 持有被装饰对象的引用  
    }  

    @Override  
    public int read() throws IOException {  
        // 增强功能:缓冲读取  
        if (pos >= count) fillBuffer();  
        return buf[pos++] & 0xff;  
    }  
}  

使用场景

  • 需要动态/透明地扩展对象功能(如加密、压缩流)
  • Android 中的 ContextWrapper 包装 Context(如 Service 包装 ContextImpl

特点

  • 装饰类和被装饰类实现相同接口
  • 可以多层嵌套,灵活组合功能

二、代理模式(Proxy)—— 中介代购

核心控制对象访问,替代原始对象处理额外逻辑
Android 源码例子:AIDL 生成的 Stub.Proxy

// frameworks/base/core/java/android/app/ActivityManagerNative.java  
class ActivityManagerProxy implements IActivityManager {  
    private final IBinder mRemote;  

    public ActivityManagerProxy(IBinder remote) {  
        mRemote = remote;  
    }  

    public int startActivity(...) throws RemoteException {  
        // 代理核心:打包数据发送给 Binder 驱动  
        Parcel data = Parcel.obtain();  
        data.writeInterfaceToken(IActivityManager.descriptor);  
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);  
    }  
}  

使用场景

  • 跨进程通信(如系统服务调用)
  • 延迟加载(如 Glide 的图片占位代理)
  • 权限控制(如检查权限后再执行实际逻辑)

特点

  • 代理类和被代理类实现相同接口
  • 重点在于访问控制而非功能增强

三、桥接模式(Bridge)—— 跨江大桥

核心分离抽象与实现,让两者独立变化
Android 源码例子View 与 Drawable 的关系

// frameworks/base/core/java/android/view/View.java  
public class View {  
    private Drawable mBackground; // 桥接的关键点  

    public void setBackground(Drawable background) {  
        mBackground = background;  
        mBackground.setBounds(...); // 委托给 Drawable 实现  
    }  
}  

// Drawable 的子类实现不同绘制逻辑  
public class ColorDrawable extends Drawable {  
    @Override  
    public void draw(Canvas canvas) {  
        canvas.drawColor(mColor);  
    }  
}  

public class BitmapDrawable extends Drawable {  
    @Override  
    public void draw(Canvas canvas) {  
        canvas.drawBitmap(mBitmap, ...);  
    }  
}  

使用场景

  • UI 框架设计(如 View 与 Drawable 解耦)
  • 跨平台渲染(如 Surface 与 OpenGL/Vulkan 桥接)
  • 数据库驱动设计(JDBC 的 Driver 与 Connection 分离)

特点

  • 抽象(如 View)持有实现(如 Drawable)的引用
  • 抽象和实现可以独立扩展(新增 View 类型不影响 Drawable 体系)

四、三种模式对比表

维度装饰模式代理模式桥接模式
核心目的动态增强对象功能控制对象访问解耦抽象与实现
关系特点装饰类与被装饰类同接口代理类与被代理类同接口抽象层持有实现层引用
调用流向单向包裹,逐层处理单向转发(可能跨进程)双向独立扩展
Android案例ContextWrapper → ContextActivityManagerProxyView + Drawable
性能影响可能增加调用链深度跨进程代理有较大开销几乎无额外开销

五、源码级原理剖析

1. 装饰模式在 Context 体系的应用

// ContextWrapper 装饰 ContextImpl  
public class ContextWrapper extends Context {  
    Context mBase; // 被装饰对象  

    public ContextWrapper(Context base) {  
        mBase = base;  
    }  

    @Override  
    public void startActivity(Intent intent) {  
        mBase.startActivity(intent); // 委托给实际实现  
    }  
}  

// Activity 继承 ContextThemeWrapper(装饰链)  
ContextImplContextWrapperContextThemeWrapperActivity  
  • 每层装饰添加新功能(如 ContextThemeWrapper 增加主题支持)

2. 代理模式在 Binder 跨进程的底层实现

// frameworks/native/libs/binder/BpBinder.cpp  
status_t BpBinder::transact(  
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
    // 通过 ioctl 与内核通信  
    return IPCThreadState::self()->transact(  
        mHandle, code, data, reply, flags);  
}  
  • 代理对象 BpBinder 只负责打包数据,实际逻辑由远端 BnBinder 处理

3. 桥接模式在 Window 系统的运用

// Window 抽象与 WindowManagerImpl 实现分离  
public abstract class Window {  
    public abstract void setContentView(View view);  
}  

public class PhoneWindow extends Window {  
    private DecorView mDecor; // 具体实现委托给 DecorView  
}  

// WindowManagerGlobal 管理实际窗口  
public class WindowManagerImpl implements WindowManager {  
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();  
}  
  • Window 负责抽象行为,WindowManagerGlobal 处理具体实现(如与 WMS 交互)

六、使用场景口诀

要增强功能用装饰,需控制访问找代理
抽象实现若多变,桥接模式来解耦

实际开发选择指南

  1. 给 RecyclerView 加滚动监听(装饰 OnScrollListener
  2. 权限校验代理网络请求(代理模式拦截非法调用)
  3. 自定义 View 支持多种渲染引擎(桥接模式分离逻辑与渲染)

注意事项

  1. 装饰模式不要嵌套超过 3 层(否则调试困难)
  2. 动态代理的性能问题(避免高频调用)
  3. 桥接模式适合框架设计,过度使用会增加类数量