设计一个发布和订阅服务(回调与接口)
本文关键字:服务 回调 接口 一个 | 更新日期: 2023-09-27 18:04:38
假设我需要一个发布数据的服务类,订阅者可以订阅感兴趣的数据。
我应该如何设计界面?传递回调是糟糕的设计吗?对我来说感觉不太好
选项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
这是一个典型的观察者模式,我肯定会选择选项2。使用界面可以提供更多选择。如果稍后需要向接口添加更多方法,则不需要更改太多代码。
我将使用委托,提供更多自由的消息有效负载,只有方法订阅而不是对象,并且不会混淆扩展/接口/mixins等。它们相当于Python中使用的pypubsub (http://pypubsub.sourceforge.net),效果非常好。
理论上,接口一旦发布到外部环境中就不应该改变。如果你决定使用一个,请记住这一点。
当然,委派的签名也是如此。此外,您总是可以提供方法重载和多个委托重载(例如,考虑Action
两种技术都有各自的优缺点;两者都不是灵丹妙药。可测试性可能会引导您使用基于接口的方法。如果有接口可以使用,模拟回调可能会容易得多。不过,使用委托也一样简单。但是,如果您使用的是mock框架或依赖注入,那么接口可能是最好的选择。