1

我有要做的事件列表。所以我将订阅者添加到订阅列表中。订阅者完成其工作后,它必须自行取消订阅。订阅者何时完成是未知的。只有订阅者自己知道这一点。

什么是最好的设计模式或解决方案。

我使用了观察者模式

这是我的 Observable:

internal class EventProvider : IObservable<double>
{
    private readonly List<IObserver<double>> _observers = new List<IObserver<double>>();

    public IDisposable Subscribe(IObserver<double> observer)
    {
        // check if observer exist...
        _observers.Add(observer);
        return new Unsubscriber<double>(_observers, observer);
    }

    public void OnTimingsRecieved(double timing) // some other event fires this
    {
        foreach (var observer in _observers)
        {
            observer.OnNext(timing);
        }
    }        

    //...
}

这是观察者:(可以有 0 到多个观察者)

internal class EventObserver : IObserver<double>
{
    private IDisposable _unsubscriber;
    private readonly IReadOnlyList<Event> _events;

    public EventObserver(IReadOnlyList<Event> events)
    {
        _events = events;
    }

    public void Subscribe(EventProvider provider)
    {
        _unsubscriber = provider.Subscribe(this);
    }

    private int _ind;
    public void OnNext(double timings)
    {
        // may move to next event or not. it depends.
        // _ind++; may execute or not 

        if (_ind == _events.Count) OnCompleted(); // time to unsubscribe it self
    }

    public void OnCompleted()
    {
        _unsubscriber.Dispose();
    } 

    //...
}

这是像往常一样实施的取消订阅者。

internal class Unsubscriber<T> : IDisposable
{
    private readonly List<IObserver<T>> _observers;
    private readonly IObserver<T> _observer;

    internal Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer)
    {
        _observers = observers;
        _observer = observer;
    }

    public void Dispose()
    {
        if (_observers.Contains(_observer))
            _observers.Remove(_observer);
    }
}

当我尝试在OnNext事件中处理观察者时出现问题。集合已修改,因为我在 foreach 循环中并且我处理了即从列表中删除的元素。

您将如何处理您想自行取消订阅订阅者的情况?有没有更好的设计模式?


我很高兴看到不同的方法,而不是使用可观察的和观察者。

假设你有这个事件。

public event EventHandler<double> TimeDiff;

并且您有许多订阅者实例附加到TimerDiff并能够自行取消订阅。

public class Reciever
{
    Jobs listOfJobsToDo;

    public void TimeDiffRecieved(double diff)
    { 
       listOfJobsToDo.DoJob(diff);
       if(somecondition)
           Unsubscribe();
    }
}
4

1 回答 1

0

由于 foreach 无法处理我用于循环的集合更改。

在这种情况下,我们知道当观察者工作时,它可以自行处理它。其他人不受影响。

这是对提供者的更正。

public void OnTimingsRecieved(double timing)
{
    for (int i = 0; i < _observers.Count; i++)
    {
        var count = _observers.Count;  // save count in case it may change.
        var observer = _observers[i];
        observer.OnNext(timing);        // it may only dispose it self.
        i -= count - _observers.Count; // decrement if observer unsubscribed.
    }
}
于 2016-12-03T11:41:22.107 回答