假设你正在开发一个外卖订单页面,包含:
这些组件需要相互通信:
传统实现方式(直接引用地狱):
class AddressPicker {
final CouponPicker couponPicker;
final PaymentPicker paymentPicker;
final ProductList productList;
final SubmitButton submitButton;
void onAddressSelected() {
// 更新运费逻辑...
productList.updateShippingFee();
couponPicker.checkApplicability();
paymentPicker.validate();
submitButton.refresh();
}
}
// 其他组件也有类似的交叉引用...
问题爆发点:
核心思想: 用一个中介对象封装一系列对象之间的交互,使各对象不需要显式相互引用,从而使其耦合松散。
四个关键角色:
abstract class OrderMediator {
void addressChanged(Address newAddress);
void couponSelected(Coupon? coupon);
void paymentMethodChanged(PaymentMethod method);
void productQuantityChanged(Product product, int quantity);
}
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();
}
}
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,
);
}
}
// 其他组件类似实现...
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),
],
),
);
}
}
// 中介者
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会收到
// 中介者
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),
// 中介者
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));
});
特性 | 中介者模式 | 观察者模式 |
---|---|---|
目的 | 集中管理对象间通信 | 一对多的依赖通知 |
耦合度 | 同事类只认识中介者 | 观察者直接订阅被观察者 |
通信方向 | 可以是双向或多向 | 通常是被观察者→观察者 |
典型应用 | 复杂UI交互、表单系统 | 状态管理、事件处理 |
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') {
// 清理订单数据...
}
}
}
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组件间有复杂的交叉调用时,中介者模式能帮你理清通信脉络!