QMUI_iOS中的中介者模式:减少对象间直接耦合
中介者模式(Mediator Pattern)是一种行为设计模式,它通过引入一个中介者对象,将系统中多个对象之间的直接交互转化为通过中介者进行间接通信,从而降低对象间的耦合度。在QMUI_iOS框架中,中介者模式被广泛应用于协调复杂UI组件间的交互,典型实现包括键盘事件管理、主题切换等核心功能模块。
键盘事件管理:QMUIKeyboardManager的中介作用
在iOS开发中,键盘事件(如显示、隐藏、frame变化)是全局通知,直接监听容易导致组件间的耦合问题。QMUIKeyboardManager作为中介者,统一管理键盘事件的分发与响应,避免了多个UI组件直接监听全局通知的混乱。
核心实现原理
QMUIKeyboardManager通过以下机制实现中介功能:
- 事件集中处理:通过
initWithDelegate:初始化,将键盘事件统一转发给delegate处理 - 目标响应者过滤:通过
addTargetResponder:指定需要响应键盘事件的UIResponder(如UITextField、UITextView),避免无关组件接收事件 - 用户信息封装:将系统键盘通知的userInfo封装为QMUIKeyboardUserInfo对象,提供便捷的属性访问(如键盘frame、动画参数等)
关键代码实现可见QMUIKeyboardManager.h:
// 初始化中介者并指定委托
- (instancetype)initWithDelegate:(id<QMUIKeyboardManagerDelegate>)delegate NS_DESIGNATED_INITIALIZER;
// 添加需要响应键盘事件的目标UIResponder
- (BOOL)addTargetResponder:(UIResponder *)targetResponder;
// 键盘frame变化时通知委托
- (void)keyboardWillChangeFrameWithUserInfo:(QMUIKeyboardUserInfo *)keyboardUserInfo;
使用场景示例
当多个输入框需要根据键盘位置调整布局时,传统方式需要每个输入框单独监听通知,而通过QMUIKeyboardManager中介者:
// 初始化键盘中介者
self.keyboardManager = [[QMUIKeyboardManager alloc] initWithDelegate:self];
// 添加需要监听的输入框
[self.keyboardManager addTargetResponder:self.usernameTextField];
[self.keyboardManager addTargetResponder:self.passwordTextField];
// 实现委托方法统一处理键盘事件
- (void)keyboardWillChangeFrameWithUserInfo:(QMUIKeyboardUserInfo *)keyboardUserInfo {
CGFloat keyboardHeight = [QMUIKeyboardManager visibleKeyboardHeight];
self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0);
}
这种方式下,所有输入框的键盘事件都通过QMUIKeyboardManager中介者转发,避免了组件间的直接依赖。
主题切换:QMUIThemeManager的集中控制
QMUIThemeManager是框架中另一个典型的中介者实现,负责统一管理应用的主题切换逻辑,协调所有UI组件的外观更新。
主题管理机制
QMUIThemeManager通过以下核心功能实现中介者角色:
- 主题注册与切换:支持添加多套主题(如浅色/深色模式),通过
currentThemeIdentifier统一切换 - 事件分发:主题变化时自动通知所有UI组件更新外观
- 系统适配:自动适配iOS 13+的Dark Mode,并转换为业务主题
核心定义可见QMUIThemeManager.h:
// 添加主题
- (void)addThemeIdentifier:(__kindof NSObject<NSCopying> *)identifier theme:(__kindof NSObject *)theme;
// 切换当前主题
@property(nonatomic, copy, nullable) __kindof NSObject<NSCopying> *currentThemeIdentifier;
// 主题变化时通知所有UI组件
extern NSNotificationName const QMUIThemeDidChangeNotification;
组件主题适配
UI组件通过实现qmui_themeDidChangeByManager:identifier:theme:方法响应主题变化,无需直接与主题管理器耦合:
// UIView+QMUITheme.h中的主题响应方法
- (void)qmui_themeDidChangeByManager:(QMUIThemeManager *)manager
identifier:(__kindof NSObject<NSCopying> *)identifier
theme:(__kindof NSObject *)theme NS_REQUIRES_SUPER;
例如按钮的主题适配实现:
- (void)qmui_themeDidChangeByManager:(QMUIThemeManager *)manager identifier:(id<NSCopying>)identifier theme:(id)theme {
[super qmui_themeDidChangeByManager:manager identifier:identifier theme:theme];
self.backgroundColor = [UIColor qmui_colorWithThemeProvider:^UIColor * _Nullable(QMUIThemeManager * _Nonnull manager, id<NSCopying> _Nullable identifier, id _Nullable theme) {
return [theme isEqual:QMUIThemeDark] ? UIColor.darkGrayColor : UIColor.lightGrayColor;
}];
}
中介者模式在QMUI_iOS中的设计优势
降低耦合度
通过QMUIKeyboardManager和QMUIThemeManager等中介者,原本需要直接交互的多个组件(如输入框、视图控制器)现在通过中介者间接通信,减少了组件间的直接引用。例如:
- 输入框不再需要直接监听
UIKeyboardWillShowNotification - UI组件无需知道主题切换的具体逻辑,只需响应中介者的通知
集中控制逻辑
中介者模式将分散在多个组件中的交互逻辑集中管理,便于维护和扩展:
- 键盘事件处理逻辑集中在QMUIKeyboardManager
- 主题切换逻辑统一由QMUIThemeManager控制
提高代码复用
中介者封装的通用逻辑可被多个组件复用,例如QMUIKeyboardManager提供的键盘frame转换方法:
// 键盘frame转换为相对于指定view的坐标
+ (CGRect)convertKeyboardRect:(CGRect)rect toView:(UIView *)view;
实际应用中的最佳实践
1. 明确中介者职责边界
避免将过多功能集中到单一中介者,QMUI_iOS中按功能划分了不同的中介者:
- 键盘管理:QMUIKeyboardManager
- 主题管理:QMUIThemeManager
- 日志管理:QMUILogger
2. 使用委托模式解耦中介者与组件
QMUIKeyboardManager通过QMUIKeyboardManagerDelegate协议与组件通信,而非直接依赖具体组件类型:
@protocol QMUIKeyboardManagerDelegate <NSObject>
@optional
- (void)keyboardWillShowWithUserInfo:(QMUIKeyboardUserInfo *)keyboardUserInfo;
- (void)keyboardWillHideWithUserInfo:(QMUIKeyboardUserInfo *)keyboardUserInfo;
@end
3. 结合通知中心实现跨层级通信
对于全局范围内的事件(如主题切换),QMUIThemeManager结合通知中心实现跨层级通信:
// 主题变化时发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:QMUIThemeDidChangeNotification
object:self
userInfo:userInfo];
组件可通过监听QMUIThemeDidChangeNotification来自行更新,无需直接引用主题管理器。
总结
QMUI_iOS框架通过QMUIKeyboardManager、QMUIThemeManager等核心组件实现了中介者模式,有效降低了UI组件间的耦合度。这种设计不仅简化了复杂交互场景的实现逻辑,还提高了代码的可维护性和扩展性。在实际开发中,合理应用中介者模式可以显著改善代码结构,尤其适用于处理多个对象之间频繁交互的场景。
更多中介者模式的实现细节,可参考QMUI_iOS框架的以下核心模块:
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



