设计发布和订阅服务(Callbacks vs Interface)

时间:2014-05-23 05:09:13

标签: c# oop callback publish-subscribe

假设我需要一个发布数据的服务类,订阅者可以订阅感兴趣的数据。

我应该如何设计界面? 传递回调是不好的设计?对我不感兴趣

选项1

public int Subscribe(string code, DataUpdatedDelegate callback) 
{
    this.subscribers[subscriptionId] = callback;
    this.codeSubscribers[code].Add(subscriptionId);
    ... 
    return subscriptionId;
}

public void UnSubscribe(int subscriptionId) 
{
    foreach list in codeSubscribers
        remove subscriptionId
    subscribers.remove(subscriptionId)
}

private void OnDataUpdated(int code, Data data)
{
     List<int> interestedSubscribers = codeSubscribers[code];
     foreach (int subId in interestedSubscribers)
     {
         DataUpdatedDelegate callback = this.subscribers[subId];
         callback(data);
     }
}

选项2

public interface ISubscriber
{
    void ProcessData(Data data);
}

public int Register(ISubscriber subscriber)
{
    return subscriptionId;
}

public void Subscribe(string code, int subscriptionId) 
{
}

... rest similar to option 1

3 个答案:

答案 0 :(得分:1)

这是一个经典的Observer模式案例,我肯定会使用选项2.使用界面可以为您提供更多选项。如果以后需要在界面中添加更多方法,则无需更改大量代码。

答案 1 :(得分:0)

我会选择代理,给予更多自由的消息有效负载,只有方法订阅不是对象,并且没有与extend / interface / mixins /等混乱。它们是Python中用于pypubsub(http://pypubsub.sourceforge.net)的C#的等价物,效果很好。

答案 2 :(得分:0)

理论上,界面一旦被释放到野外就不应该改变。如果您决定使用它,请记住这一点。

当然,代表的签名也是如此。然后,您可以始终提供方法重载和多个委托重载(例如,考虑Action&lt; T&gt;,Action&lt; T1,T2&gt;等)。

这两种技术都有其优点和缺点;也不是银弹。可能引导您采用基于接口的方法的是可测试性。如果您有一个要使用的接口,那么模拟回调可能会容易得多。再说一次,代表可能也很容易。但是,如果您正在使用模拟框架或依赖注入,那么接口可能就好了。