中介者模式 - Flutter中的通信指挥中心,告别组件间混乱对话!
痛点场景:订单页面的组件纠缠
假设你正在开发一个外卖订单页面,包含:
- 地址选择器
- 优惠券选择器
- 支付方式选择
- 商品列表
- 提交按钮
这些组件需要相互通信:
- 选择地址 → 更新运费 → 刷新总价
- 选择优惠券 → 校验是否适用于当前商品 → 更新折扣 → 刷新总价
- 切换支付方式 → 检查是否支持优惠券 → 更新按钮状态
- 修改商品数量 → 检查库存 → 更新优惠券可用性
传统实现方式(直接引用地狱):
class AddressPicker {final CouponPicker couponPicker;final PaymentPicker paymentPicker;final ProductList productList;final SubmitButton submitButton;void onAddressSelected() {// 更新运费逻辑...productList.updateShippingFee();couponPicker.checkApplicability();paymentPicker.validate();submitButton.refresh();}
}
// 其他组件也有类似的交叉引用...
问题爆发点:
- 🕸️ 组件间形成蜘蛛网般的耦合
- 💥 修改一个组件会影响多个其他组件
- 🔥 难以单独测试某个组件
- 🌋 添加新组件需要修改大量现有代码
中介者模式解决方案
核心思想: 用一个中介对象封装一系列对象之间的交互,使各对象不需要显式相互引用,从而使其耦合松散。
四个关键角色:
- 中介者接口(Mediator): 定义通信接口
- 具体中介者(ConcreteMediator): 协调各组件交互
- 同事类(Colleague): 需要通信的组件
- 同事接口(Colleague): 定义组件通用接口(可选)
Flutter订单中介者实现
1. 定义中介者接口
abstract class OrderMediator {void addressChanged(Address newAddress);void couponSelected(Coupon? coupon);void paymentMethodChanged(PaymentMethod method);void productQuantityChanged(Product product, int quantity);
}
2. 实现具体中介者
class OrderController implements OrderMediator {final AddressPicker _addressPicker;final CouponPicker _couponPicker;final PaymentPicker _paymentPicker;final ProductList _productList;final SubmitButton _submitButton;OrderController({required AddressPicker addressPicker,required CouponPicker couponPicker,// 其他组件...}) : _addressPicker = addressPicker,_couponPicker = couponPicker,// 初始化其他组件...{// 设置组件的中介者引用_addressPicker.mediator = this;_couponPicker.mediator = this;// ...}void addressChanged(Address newAddress) {final shippingFee = _calculateShippingFee(newAddress);_productList.updateShippingFee(shippingFee);_couponPicker.checkApplicability();_submitButton.refresh();}void couponSelected(Coupon? coupon) {if (coupon != null && !_productList.isCouponApplicable(coupon)) {_couponPicker.showError('此优惠券不适用于当前商品');return;}_paymentPicker.validateCoupon(coupon);_productList.applyCoupon(coupon);_submitButton.refresh();}void paymentMethodChanged(PaymentMethod method) {if (!method.supportsCoupons && _couponPicker.selectedCoupon != null) {_couponPicker.clearSelection();_productList.removeCoupon();}_submitButton.refresh();}void productQuantityChanged(Product product, int quantity) {_couponPicker.checkApplicability();_paymentPicker.validate();_submitButton.refresh();}
}
3. 创建同事类(组件)
abstract class OrderComponent {OrderMediator? mediator;
}class AddressPicker extends StatefulWidget implements OrderComponent { OrderMediator? mediator; _AddressPickerState createState() => _AddressPickerState();
}class _AddressPickerState extends State<AddressPicker> {Address? _selectedAddress;void _handleAddressChange(Address newAddress) {setState(() => _selectedAddress = newAddress);widget.mediator?.addressChanged(newAddress);} Widget build(BuildContext context) {return DropdownButton<Address>(value: _selectedAddress,items: _buildAddressItems(),onChanged: _handleAddressChange,);}
}// 其他组件类似实现...
4. 在页面中组装
class OrderPage extends StatefulWidget { _OrderPageState createState() => _OrderPageState();
}class _OrderPageState extends State<OrderPage> {late final OrderMediator _mediator;void initState() {super.initState();final addressPicker = AddressPicker();final couponPicker = CouponPicker();// 初始化其他组件..._mediator = OrderController(addressPicker: addressPicker,couponPicker: couponPicker,// 注入其他组件...);} Widget build(BuildContext context) {return Scaffold(body: Column(children: [AddressPicker(mediator: _mediator),CouponPicker(mediator: _mediator),PaymentPicker(mediator: _mediator),ProductList(mediator: _mediator),SubmitButton(mediator: _mediator),],),);}
}
Flutter中的实际应用场景
场景1:聊天室系统
// 中介者
class ChatRoom implements ChatMediator {final List<User> _users = [];void register(User user) {_users.add(user);}void sendMessage(String message, User sender) {for (final user in _users) {if (user != sender) {user.receive(message);}}}
}// 同事类
class User {final String name;final ChatMediator mediator;User(this.name, this.mediator);void send(String message) {print('$name 发送: $message');mediator.sendMessage(message, this);}void receive(String message) {print('$name 收到: $message');}
}// 使用
final chatRoom = ChatRoom();
final john = User('John', chatRoom);
final jane = User('Jane', chatRoom);
chatRoom.register(john);
chatRoom.register(jane);john.send('Hi there!'); // Jane会收到
jane.send('Hello!'); // John会收到
场景2:表单验证系统
// 中介者
class FormValidator implements FormMediator {final List<FormField> _fields = [];void registerField(FormField field) {_fields.add(field);}void validateAll() {bool isValid = true;for (final field in _fields) {if (!field.validate()) {isValid = false;}}submitButton.setEnabled(isValid);}
}// 同事类
class EmailField extends StatefulWidget implements FormField { FormMediator? mediator; bool validate() {// 验证逻辑...mediator?.validateAll();}
}// 在表单中使用
final validator = FormValidator();
EmailField(mediator: validator),
PasswordField(mediator: validator),
SubmitButton(mediator: validator),
场景3:电商筛选系统
// 中介者
class FilterMediator {final List<FilterWidget> _filters = [];ProductList? _productList;void registerFilter(FilterWidget filter) {_filters.add(filter);}void registerProductList(ProductList list) {_productList = list;}void onFilterChanged() {final filters = _filters.map((f) => f.currentFilter).toList();_productList?.applyFilters(filters);}
}// 使用
final mediator = FilterMediator();
ColorFilter(mediator: mediator),
PriceFilter(mediator: mediator),
BrandFilter(mediator: mediator),
ProductList(mediator: mediator),
中介者模式与状态管理的结合
将中介者与Provider结合:
// 中介者提供者
class OrderMediatorProvider extends ChangeNotifier {final OrderMediator _mediator;OrderMediatorProvider(this._mediator);OrderMediator get mediator => _mediator;
}// 顶层注册
void main() {final addressPicker = AddressPicker();final mediator = OrderController(addressPicker: addressPicker);runApp(MultiProvider(providers: [ChangeNotifierProvider(create: (_) => OrderMediatorProvider(mediator)),],child: MyApp(),),);
}// 在组件中使用
Consumer<OrderMediatorProvider>(builder: (context, provider, child) {return AddressPicker(mediator: provider.mediator);}
)
中介者模式最佳实践
-
何时使用中介者模式:
- 系统中有大量对象需要相互通信
- 对象间引用关系复杂难以理解
- 想定制分布在多个类中的行为又不想生成太多子类
- 通信逻辑需要集中管理
-
Flutter特化技巧:
// 使用事件总线增强中介者 class EventBusMediator implements OrderMediator {final EventBus _bus;EventBusMediator(this._bus);void addressChanged(Address newAddress) {_bus.fire(AddressChangedEvent(newAddress));} }// 组件监听事件 _bus.on<AddressChangedEvent>().listen((e) {// 处理地址变更 });
-
性能优化:
// 懒加载中介者 class LazyMediator implements OrderMediator {OrderController? _controller;void addressChanged(Address newAddress) {_controller ??= OrderController(...);_controller!.addressChanged(newAddress);} }
-
测试策略:
test('地址变更应更新运费', () {final mediator = MockOrderMediator();final addressPicker = AddressPicker(mediator: mediator);addressPicker.selectAddress(testAddress);verify(mediator.addressChanged(testAddress)); });
中介者模式 vs 观察者模式
特性 | 中介者模式 | 观察者模式 |
---|---|---|
目的 | 集中管理对象间通信 | 一对多的依赖通知 |
耦合度 | 同事类只认识中介者 | 观察者直接订阅被观察者 |
通信方向 | 可以是双向或多向 | 通常是被观察者→观察者 |
典型应用 | 复杂UI交互、表单系统 | 状态管理、事件处理 |
中介者模式的高级变体
1. 分层中介者
class GlobalMediator {final List<DomainMediator> _domainMediators = [];void registerDomain(DomainMediator mediator) {_domainMediators.add(mediator);}void notifyAll(String globalEvent) {for (final mediator in _domainMediators) {mediator.handleGlobalEvent(globalEvent);}}
}class OrderMediator implements DomainMediator {void handleGlobalEvent(String event) {if (event == 'USER_LOGGED_OUT') {// 清理订单数据...}}
}
2. 中介者+命令模式
abstract class MediatorCommand {void execute(OrderMediator mediator);
}class AddressChangeCommand implements MediatorCommand {final Address newAddress;AddressChangeCommand(this.newAddress);void execute(OrderMediator mediator) {mediator.addressChanged(newAddress);}
}// 在组件中使用
void _handleAddressChange(Address newAddress) {final command = AddressChangeCommand(newAddress);command.execute(widget.mediator);
}
总结:中介者模式是你的通信枢纽
- 核心价值: 将网状通信结构变为星型结构,降低系统复杂度
- Flutter优势:
- 解耦UI组件
- 集中管理业务逻辑
- 简化组件测试
- 提高代码可维护性
- 适用场景: 复杂表单、电商筛选、聊天系统、多步骤流程
🎛️ 设计启示: 当你发现Flutter组件间有复杂的交叉调用时,中介者模式能帮你理清通信脉络!