You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以及为何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:09:02