一句话总结:
外观模式像「酒店前台」—— 一个窗口搞定所有服务,中介模式像「婚庆司仪」—— 协调各方避免新人自己对接,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交互 - 内部整合了
PackageManager、Resources、WindowManager等子系统
使用场景:
- 启动四大组件
- 获取系统服务
- 访问资源文件
特点:
- 单向调用:用户 → 外观 → 子系统
- 不改变原有架构,只是提供便捷入口
二、中介模式(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(),无需了解Engine、DiskCache等模块
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作为中介者协调Looper、MessageQueue、Activity的消息传递
五、使用场景口诀
「入口复杂用外观,交互混乱找中介
实际开发选择指南:
- 工具类封装:用外观模式(如
ImageLoader.with(context)) - 组件通信:用中介模式(如用
ViewModel协调 Fragment 数据) - 事件分发:中介模式(如点击事件统一处理)
- SDK 设计:优先外观模式(降低用户使用成本)
注意事项:
- 外观类不要过度膨胀(否则变成上帝类)
- 中介模式要注意线程安全(尤其是多线程场景)
- 避免在中介者中写业务逻辑(应保持中介者职责单一)