我们有一个管理许多存储数据的队列的类。我希望用户在将新数据添加到每个队列时收到通知。我想使用委托和事件来使用观察者模式。通常对于单个事件和来源,我们会这样做:
public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate NewDataAdded;
和观察员:
qManager.NewDataAdded += new qManager.NewDataAddedDelegate(getNewDataFunc);
但在这种情况下,我们有10个队列,每个队列都可以任意接收数据。所以我们希望观察者函数订阅一个单独的队列。我们认为我们可以做到:
public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate [] NewDataAdded; // can't do this
并在qManager的构造函数中:
NewDataAdded = new NewDataAddedDelegate[numberOfQueues];
并在观察者中:
qManager.NewDataAdded[0] += new qManager.NewDataAddedDelegate(getNewDataFunc0);
qManager.NewDataAdded[1] += new qManager.NewDataAddedDelegate(getNewDataFunc1);
但没有去,因为事件应该是委托类型,而不是委托类型数组。
有关如何解决此问题的任何想法?
答案 0 :(得分:4)
不,事件不会那样。选项:
创建另一个公开事件的类型,并拥有该类型的数组或集合:
// Preferably *don't* just expose an array...
public TypeWithEvent[] Queues { get { ... } }
// Subscription:
qManager.Queues[i].NewDataAdded += ...
或者,不要使用事件,只需要一个方法:
private NewDataAddededDelegate[] newDataAdded;
public void SubscribeNewDataAddedHandler(int queue,
NewDataAddedDelegate handler)
{
newDataAdded[queue] += handler;
}
// Subscription
qManager.SubscribeNewDataAddedHandler(0, ...);
我个人觉得每个队列都应该是它自己的对象,但是......让队列管理器公开一个队列集合,每个队列都可以单独订阅。 (即采取第一种方法。)否则你的队列管理员真的做了太多的工作。
答案 1 :(得分:3)
你可以采取两种方法;首先是:
private NewDataAddedDelegate[] queues; // init not shown
public void Subscribe(int index, NewDataAddedDelegate handler) {
queues[index] += handler;
}
并使用
obj.Subscribe(index, ...);
但您可能想要考虑订阅周围的同步等。第二种方法是创建一个包含事件的包装类 - 然后你可以使用编译器的同步,这在C#4.0中很好:
public class SomeQueue {
public event NewDataAddedDelegate NewDataAdded;
}
然后通过索引器公开那些,所以你有
obj.Queues[index].NewDataAdded += ...
就个人而言,我预计第一个会更容易。只有同步可能会令人讨厌。我在一些pub-sub代码中执行此操作,而在订阅期间我只是lock
。
答案 2 :(得分:2)
你需要通过实际应用observer pattern来重新考虑这一点,而不是基于模式的模糊概念。
定义您的IObserver和ISubject接口,并尝试了解观察者是什么以及主题是什么。在你的情况下,听起来像队列是主题,不确定观察者在你的领域模型中会是什么。
一旦你这样做,事情将更容易弄明白,而这只是实现你的接口声明的方法的问题,例如你的主题(队列)将只调用notify(并且如果你想使用就引发一个事件)代理人)当事情发生时(项目被添加到队列中)。
希望这有帮助。
答案 3 :(得分:0)
也许您可以使用Event Aggregator pattern。
并不是说您需要编写更少的代码,但它可以创建更干净/可维护的代码。
答案 4 :(得分:0)
这是C#中的工作代码。
QueueManger公开可由一个或多个观察者订阅的事件NewDataAddedEvent。 Queue在数据更改时调用QueueManager上的NewDataAdded()方法。 QueueManager通知是否有任何具有参数Queue的订户。我希望这可以解决你的问题。
using System;
using System.Collections.Generic;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
QueueManager queueManager = new QueueManager();
Observer observer = new Observer(queueManager);
Queue queue1 = queueManager.AddQueue();
Queue queue2 = queueManager.AddQueue();
queue1.OnNewDataAdd();
queue2.OnNewDataAdd();
Console.ReadLine();
}
delegate void NewDataAddedDelegate(Queue queue);
class Queue
{
QueueManager queueManager;
public string id;
public Queue(string id, QueueManager queueManager)
{
this.id = id;
this.queueManager = queueManager;
}
public void OnNewDataAdd()
{
this.queueManager.NewDataAdded(this);
}
}
class QueueManager
{
List<Queue> queues = new List<Queue>();
public Queue AddQueue()
{
Queue queue = new Queue((queues.Count + 1).ToString(), this);
this.queues.Add(queue);
return queue;
}
public event NewDataAddedDelegate NewDataAddedEvent;
public void NewDataAdded(Queue queue)
{
if (NewDataAddedEvent != null)
NewDataAddedEvent(queue);
}
}
class Observer
{
public Observer(QueueManager queueManager)
{
queueManager.NewDataAddedEvent += new NewDataAddedDelegate(queue_NewDataAdded);
}
void queue_NewDataAdded(Queue queue)
{
Console.WriteLine("Notification to the observer from queue {0}", queue.id);
}
}
}
}