泛型的观察者模式



我在阅读MSDN文档后尝试学习观察者模式:https://learn.microsoft.com/en-us/dotnet/standard/events/observer-design-pattern。与继承一起使用时,它会出错并且不允许我创建公共观察器。下面是我的代码:

interface Book { }
class ComicBook : Book { }
class ComicBookObserver : IObserver<ComicBook>
{
public void OnCompleted() { throw new NotImplementedException(); }
public void OnError(Exception error) { throw new NotImplementedException(); }
public void OnNext(ComicBook value) { throw new NotImplementedException(); }
}
class Publisher : IObservable<Book>
{
private List<IObserver<ComicBook>> ComicBookObservers = new List<IObserver<ComicBook>>();
public IDisposable Subscribe(IObserver<Book> observer) 
{
if (observer is IObserver<ComicBook>)
ComicBookObservers.Add(observer);
return null;
}
}
class Main
{
public static void main(string[] args)
{
Publisher p = new Publisher();
p.Subscribe(new ComicBookObserver());
}
}

我在p.Subscribe(new ComicBookObserver());收到错误:

Cannot convert from 'ComicBookObserver' to 'System.IObserver<Book>'

为什么会这样,因为漫画书也是一本书。这是不允许的吗?我是否必须为所有不同类型的书籍创建Subcribe方法?

在您的示例中,ComicBookObserver实现了IObserver<ComicBook>,因此它希望看到ComicBook

Publisher实现IObservable<Book>,因此输出Book

Book接口不满足ComicBookObserver所需的派生ComicBook类型。

如果您需要观察特定类型,那么是的,您需要多次订阅特定于这些类型的订阅者。

您可以使用 RxOfType<ComicBook>()方法从您的IObservable<Book>创建新的可观察量。

例如:

发布者 p = 新发布者((; p.OfType((.订阅(新漫画观察家(((;

这样做的好处是,只会观察类型ComicBook的项目,并且不需要执行任何其他类型检查。

我认为你可以继续你的模式,但添加一个皱纹。 我会让 ComicBook 观察者实现IObserver<Book>然后在您的实现中您需要处理ComicBook项目并丢弃其余项目。 可以说,您将为其他观察者订阅其他类型的书籍。 他们也会遵循这种模式。

interface Book { }
class ComicBook : Book { }
class OtherBook : Book { }
class ComicBookObserver : IObserver<Book>
{
public void OnCompleted() { throw new NotImplementedException(); }
public void OnError(Exception error) { throw new NotImplementedException(); }
public void OnNext(Book value) 
{   
if (value is ComicBook)
{
// logic for Comic Book values
}
}
}
class OthereBookObserver : IObserver<Book>
{
public void OnCompleted() { throw new NotImplementedException(); }
public void OnError(Exception error) { throw new NotImplementedException(); }
public void OnNext(Book value) 
{   
if (value is OtherBook)
{
// logic for other book values
}
}
}
class Publisher : IObservable<Book>
{
public IDisposable Subscribe(IObserver<Book> observer) { throw new NotImplementedException(); }
}
class Main
{
public static void main(string[] args)
{
Publisher p = new Publisher();
p.Subscribe(new ComicBookObserver());
p.Subscribe(new OtherBookObserver());
}
}

最新更新