中介者模式 - Flutter中的通信指挥中心,告别组件间混乱对话!

发布于:2025-06-30 ⋅ 阅读:(16) ⋅ 点赞:(0)

痛点场景:订单页面的组件纠缠

假设你正在开发一个外卖订单页面,包含:

  • 地址选择器
  • 优惠券选择器
  • 支付方式选择
  • 商品列表
  • 提交按钮

这些组件需要相互通信:

  1. 选择地址 → 更新运费 → 刷新总价
  2. 选择优惠券 → 校验是否适用于当前商品 → 更新折扣 → 刷新总价
  3. 切换支付方式 → 检查是否支持优惠券 → 更新按钮状态
  4. 修改商品数量 → 检查库存 → 更新优惠券可用性

传统实现方式(直接引用地狱):

class AddressPicker {
  final CouponPicker couponPicker;
  final PaymentPicker paymentPicker;
  final ProductList productList;
  final SubmitButton submitButton;
  
  void onAddressSelected() {
    // 更新运费逻辑...
    productList.updateShippingFee();
    couponPicker.checkApplicability();
    paymentPicker.validate();
    submitButton.refresh();
  }
}
// 其他组件也有类似的交叉引用...

问题爆发点:

  • 🕸️ 组件间形成蜘蛛网般的耦合
  • 💥 修改一个组件会影响多个其他组件
  • 🔥 难以单独测试某个组件
  • 🌋 添加新组件需要修改大量现有代码

中介者模式解决方案

核心思想: 用一个中介对象封装一系列对象之间的交互,使各对象不需要显式相互引用,从而使其耦合松散。

四个关键角色:

  1. 中介者接口(Mediator): 定义通信接口
  2. 具体中介者(ConcreteMediator): 协调各组件交互
  3. 同事类(Colleague): 需要通信的组件
  4. 同事接口(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);
  }
)

中介者模式最佳实践

  1. 何时使用中介者模式:

    • 系统中有大量对象需要相互通信
    • 对象间引用关系复杂难以理解
    • 想定制分布在多个类中的行为又不想生成太多子类
    • 通信逻辑需要集中管理
  2. Flutter特化技巧:

    // 使用事件总线增强中介者
    class EventBusMediator implements OrderMediator {
      final EventBus _bus;
      
      EventBusMediator(this._bus);
      
      
      void addressChanged(Address newAddress) {
        _bus.fire(AddressChangedEvent(newAddress));
      }
    }
    
    // 组件监听事件
    _bus.on<AddressChangedEvent>().listen((e) {
      // 处理地址变更
    });
    
  3. 性能优化:

    // 懒加载中介者
    class LazyMediator implements OrderMediator {
      OrderController? _controller;
      
      
      void addressChanged(Address newAddress) {
        _controller ??= OrderController(...);
        _controller!.addressChanged(newAddress);
      }
    }
    
  4. 测试策略:

    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组件间有复杂的交叉调用时,中介者模式能帮你理清通信脉络!