如何以及为何使用Events与delegates?直接方法调用可用时的使用疑问
委托与事件的实际使用价值说明
你当前的实现之所以能用,是因为你的业务逻辑还处于非常简单的阶段,只有单一后续操作。一旦业务复杂度上升,直接调用的写法会迅速变得难以维护,委托和事件正是为了解决这类耦合问题设计的。
现有实现的潜在问题
你现在的代码存在非常强的紧耦合问题:
Shop类、Deposit类都直接强依赖UserWallet类,一旦UserWallet的方法名、参数发生变化,所有调用的地方都要跟着改- 后续如果要新增业务逻辑,必须修改原有触发逻辑的代码,违反开闭原则
举个实际的业务迭代场景:现在运营要求用户购买商品成功后,需要新增3个操作:给用户发送消费短信通知、给用户账户增加对应会员积分、生成消费流水计入财务系统。按照你现有的写法,你必须修改BuyOrderFilled方法,在里面新增三个类的方法调用,后续每次加需求都要改这个核心方法,很容易改出问题。
用事件优化后的实现逻辑
我们可以把**「购买订单完成」「出售订单完成」「充值成功」这类动作抽象为事件**,事件的发布方不需要关心谁要监听这个事件,只需要在动作触发时广播事件即可,所有关心这个事件的业务方自己订阅处理:
// 定义委托(约定事件处理方法的签名) public delegate void OrderFilledHandler(User user); public delegate void DepositSuccessHandler(User user, decimal amount); class Shop { // 定义购买订单完成事件 public static event OrderFilledHandler OnBuyOrderFilled; // 定义出售订单完成事件 public static event OrderFilledHandler OnSellOrderFilled; public static void BuyOrderFilled(User user){ if(userHasBalance(user)){ UserWallet userWallet = new UserWallet(); userWallet.DeductMoney(user); } UpdateInventory(); // 广播事件,所有订阅的方法都会自动执行 OnBuyOrderFilled?.Invoke(user); } public static void SellOrderFilled(User user){ if(userHasProduct(user)){ UserWallet userWallet = new UserWallet(); userWallet.RemoveProductFromUser(user); } UpdateInventory(); OnSellOrderFilled?.Invoke(user); } } class Deposit{ // 定义充值成功事件 public static event DepositSuccessHandler OnDepositSuccess; public static void UserGotDeposit(User user, decimal amount){ UserWallet userWallet = new UserWallet(); userWallet.FillUserBalance(user, amount); // 广播充值成功事件 OnDepositSuccess?.Invoke(user, amount); } } // 后续新增的业务类,不需要修改Shop、Deposit的原有代码 class SmsService{ public SmsService(){ // 订阅购买成功事件,订单完成后自动发消费短信 Shop.OnBuyOrderFilled += SendConsumeSms; // 订阅充值成功事件,充值后自动发到账短信 Deposit.OnDepositSuccess += SendDepositSms; } private void SendConsumeSms(User user){ // 发送消费短信逻辑 } private void SendDepositSms(User user, decimal amount){ // 发送充值到账短信逻辑 } } class PointsService{ public PointsService(){ Shop.OnBuyOrderFilled += AddConsumePoints; } private void AddConsumePoints(User user){ // 增加会员积分逻辑 } }
委托/事件的核心优势
- 解耦:事件发布方不需要依赖任何订阅方的代码,比如
Shop类完全不知道SmsService、PointsService的存在,也不需要引用相关类,双方只依赖约定的委托签名 - 易扩展:新增业务逻辑不需要修改核心触发代码,比如后续要加「购买成功后发优惠券」的逻辑,只需要新增一个
CouponService,订阅OnBuyOrderFilled事件即可,不需要动Shop类的一行代码 - 动态灵活:可以在运行时动态添加/移除订阅,比如大促期间临时开启「充值成功送满减券」的活动,只需要在活动开始时给
OnDepositSuccess加订阅,活动结束时移除订阅即可,不需要修改核心业务逻辑
你的现有实现只适合逻辑固定、不会迭代的简单场景,只要项目需要持续迭代、新增需求,委托和事件能帮你大幅降低代码维护成本,避免核心逻辑被频繁修改导致的bug。
内容的提问来源于stack exchange,提问作者Guga Todua
相关产品推荐
相关产品推荐

