观察者模式 (C#)






4.89/5 (38投票s)
在 C# 中实现观察者设计模式
引言
此技巧介绍了一种非常有趣的设计模式 - 观察者设计模式。 我在 Google 博客上写了这个技巧,但我现在将其移植到适当的位置。
背景
观察者设计模式是另一种我最喜欢的设计模式,它属于“行为模式”类别。顾名思义,我们可以说观察者是观察其他对象(在 OOPS 的情况下)。观察者模式通常被称为基于“好莱坞原则”,该原则说:“不要打电话给我们,我们会打电话给你。”Pub-Sub (发布者-订阅者) 是给予观察者模式的另一个流行的昵称。
基于“好莱坞原则”,我们可以猜测在观察者模式中,有一个特殊的好莱坞名人对象,所有其他普通对象都对此感兴趣。实际上,在观察者模式中 - “有 n 个 观察者(对象)对一个特殊的对象(称为主题)感兴趣。”进一步解释 - 有各种对象(称为观察者)对一个特殊对象(称为主题)正在发生的事情感兴趣。因此,他们将自己注册(或订阅)到主题(也称为发布者)。观察者对事件的发生感兴趣(此事件通常发生在主题对象的边界内),每当此事件被主题/发布者引发时,观察者都会收到通知(他们已订阅此事件的发生 - 还记得吗?)
Using the Code
可以通过编写不必要的文献来使简单的概念变得复杂。让我们深入研究一个实际的示例和代码,以清除有关观察者模式的所有内容。考虑一家在线电子商店,该商店拥有大量的库存并不断更新。商店希望在任何产品到货时更新其所有用户/客户。 只需阅读问题陈述,我们就可以将 观察者模式 应用于上述问题 - 如何?在线电子商店将成为主题。每当主题的库存有任何增加时,已订阅商店通知的观察者(客户/用户)将通过电子邮件收到通知。 让我们直接看代码,以了解我们如何在 C# 中实现观察者模式。
主题
public class Subject:ISubject
{
private List<Observer> observers = new List<Observer>();
private int _int;
public int Inventory
{
get
{
return _int;
}
set
{
// Just to make sure that if there is an increase in inventory then only we are notifying
the observers.
if (value > _int)
Notify();
_int = value;
}
}
public void Subscribe(Observer observer)
{
observers.Add(observer);
}
public void Unsubscribe(Observer observer)
{
observers.Remove(observer);
}
public void Notify()
{
observers.ForEach(x => x.Update());
}
}
interface ISubject
{
void Subscribe(Observer observer);
void Unsubscribe(Observer observer);
void Notify();
}
“主题”维护“观察者”的列表。由于每个主题都可能有一些这样的方法,我将它们绑定到一个接口中。Subscribe
-Unsubscribe
方法是观察者向主题注册-取消注册的方法。Notify
方法负责通知所有观察者。
让我们看一下 Observer
类的代码
public class Observer:IObserver
{
public string ObserverName { get;private set; }
public Observer(string name)
{
this.ObserverName = name;
}
public void Update()
{
Console.WriteLine("{0}: A new product has arrived at the
store",this.ObserverName);
}
}
interface IObserver
{
void Update();
}
Observer
类相当简单,因为它只有一个属性 (ObserverName
) 用于区分一个观察者和另一个观察者,并且它还有一个 Update
方法。 这是几乎每个 observer
类都具有的方法。 这是 Observer
接收到 Subject
中发生某些事情的通知的方式,并且由于 Observer
已注册以接收通知,因此它通过此方法收到通知。
让我们看一下 main 方法,它将完成我们使用观察者模式的代码。
static void Main(string[] args)
{
Subject subject = new Subject();
// Observer1 takes a subscription to the store
Observer observer1 = new Observer("Observer 1");
subject.Subscribe(observer1);
// Observer2 also subscribes to the store
subject.Subscribe(new Observer("Observer 2"));
subject.Inventory++;
// Observer1 unsubscribes and Observer3 subscribes to notifications.
subject.Unsubscribe(observer1);
subject.Subscribe(new Observer("Observer 3"));
subject.Inventory++;
Console.ReadLine();
}
此 Main
方法非常简单。 我们创建 Subject
的一个实例,以便我们可以订阅/取消订阅不同的观察者。 当 Subject
中的库存发生变化时,我们通过他们的 Update
方法通知观察者(查看 Subject
类中的代码)。
以下是程序的输出...
如果您注意到,在第一次通知后,由于 Observer1
已取消订阅,因此下次库存发生变化时它将不会收到通知。 但是由于 Observer3
已订阅 Observers
列表,因此当 Subject
中有更新时,它会收到通知。
关注点
以上用于实现观察者模式的代码非常简单。 我们可以通过更复杂的方式来实现观察者模式。 一种方法是通过委托和事件,这在实现观察者模式中非常自然(请查看我关于事件和委托的文章 [事件和委托],那里编写的代码是观察者模式的实现)。 C# 现在本身支持 Observable
类/框架,可用于实现观察者模式。 也许,我将在另一篇文章中重新审视观察者模式,以查看该框架。 此外,我们将讨论主题和观察者如何实现拉取通知和推送通知。
历史
- 版本 1 - (2014 年 5 月 6 日)