一句话说透Android里面的外观模式和中介模式的区别

159 阅读3分钟

一句话总结:
外观模式像「酒店前台」—— 一个窗口搞定所有服务,中介模式像「婚庆司仪」—— 协调各方避免新人自己对接,Android 系统里两者各司其职,一个简化入口,一个解耦交互!


一、外观模式(Facade)—— 酒店前台

核心统一入口简化操作,隐藏子系统复杂性
Android 源码例子Context 类

// frameworks/base/core/java/android/content/Context.java  
public abstract class Context {  
    // 外观模式的集大成者,一个类封装上百个系统服务访问入口  
    public abstract void startActivity(Intent intent);  
    public abstract Object getSystemService(String name);  
    public abstract Resources getResources();  
    public abstract PackageManager getPackageManager();  
}  

// 实际实现类 ContextImpl  
class ContextImpl extends Context {  
    @Override  
    public void startActivity(Intent intent) {  
        // 内部调用 ActivityTaskManagerService(ATMS)等复杂流程  
        mMainThread.getActivityTaskManager().startActivity(...);  
    }  
}  

底层原理

  • 用户只需调用 context.startActivity(),无需知道底层如何与 ActivityTaskManagerService 交互
  • 内部整合了 PackageManagerResourcesWindowManager 等子系统

使用场景

  • 启动四大组件
  • 获取系统服务
  • 访问资源文件

特点

  • 单向调用:用户 → 外观 → 子系统
  • 不改变原有架构,只是提供便捷入口

二、中介模式(Mediator)—— 婚庆司仪

核心集中管理对象间交互,避免网状依赖
Android 源码例子LiveData 的数据传递

// frameworks/base/core/java/androidx/lifecycle/LiveData.java  
public abstract class LiveData<T> {  
    // 中介者维护观察者列表  
    private final ArrayMap<Observer<? super T>, ObserverWrapper> mObservers = new ArrayMap<>();  

    // 统一处理数据变更通知  
    @MainThread  
    protected void setValue(T value) {  
        mData = value;  
        dispatchingValue(null); // 中介调度中心  
    }  

    private void dispatchingValue(@Nullable ObserverWrapper initiator) {  
        // 遍历所有观察者并通知  
        for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =  
            mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {  
            considerNotify(iterator.next().getValue());  
        }  
    }  
}  

底层原理

  • LiveData 作为中介者,管理所有观察者(Activity/Fragment)
  • 数据变更时统一调度,避免观察者之间直接相互调用

使用场景

  • 跨 Fragment 通信
  • 事件总线(如 EventBus 的订阅/发布机制)
  • 聊天室消息分发

特点

  • 多向交互:各对象只与中介通信
  • 中介持有所有交互对象的引用

三、模式对比表

维度外观模式中介模式
核心目标简化复杂系统的使用入口解耦多对象间的网状依赖
交互方向单向:用户 → 外观 → 子系统双向:同事对象 ↔ 中介 ↔ 同事对象
结构特点通常只有一层包装需要维护多个对象的引用
Android案例Context、Glide.with()LiveData、Handler
性能影响几乎无额外开销中介可能成为性能瓶颈(如密集事件)

四、源码级原理剖析

1. 外观模式在 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();  
    }  
}  
  • 用户只需调用 Glide.with().load().into(),无需了解 EngineDiskCache 等模块

2. 中介模式在 Handler 消息机制中的实现

// frameworks/base/core/java/android/os/Handler.java  
public class Handler {  
    // 中介者持有 MessageQueue 和 Looper  
    final Looper mLooper;  
    final MessageQueue mQueue;  

    public void handleMessage(Message msg) { /* 空方法,需重写 */ }  

    // 统一处理消息分发  
    public void dispatchMessage(Message msg) {  
        if (msg.callback != null) {  
            handleCallback(msg);  
        } else {  
            if (mCallback != null) {  
                if (mCallback.handleMessage(msg)) return;  
            }  
            handleMessage(msg); // 最终交给开发者处理  
        }  
    }  
}  
  • Handler 作为中介者协调 LooperMessageQueueActivity 的消息传递

五、使用场景口诀

入口复杂用外观,交互混乱找中介

实际开发选择指南

  1. 工具类封装:用外观模式(如 ImageLoader.with(context)
  2. 组件通信:用中介模式(如用 ViewModel 协调 Fragment 数据)
  3. 事件分发:中介模式(如点击事件统一处理)
  4. SDK 设计:优先外观模式(降低用户使用成本)

注意事项

  1. 外观类不要过度膨胀(否则变成上帝类)
  2. 中介模式要注意线程安全(尤其是多线程场景)
  3. 避免在中介者中写业务逻辑(应保持中介者职责单一)