C# 中的观察者模式理解与实现






4.93/5 (18投票s)
C# 中的观察者模式理解与实现
引言
本文介绍了观察者模式的基本原理、何时使用以及如何在 C# 中实现它。
背景
很多时候,我们需要应用程序的一个部分根据应用程序其他部分的的状态进行更新。一种方法是让接收方部分反复检查发送方是否有更新,但这种方法存在两个主要问题。首先,它会占用大量的 CPU 时间来检查新状态;其次,根据我们检查更改的间隔,我们可能无法“立即”获得更新。
这个问题有一个简单的解决方案,那就是观察者模式。我知道很多人在阅读这篇文章时会批评我,因为这可能是 CodeProject 上关于观察者模式的第 100 篇文章,但我仍然认为分享它是有价值的,因为它对初学者来说可能很有用,而且我从文章中获得的宝贵评论也能让我学到更多。
这是观察者模式的类图(参考:GoF 设计模式)

Using the Code
现在让我们逐一讨论所有类
Subject
:此类跟踪所有观察者,并提供添加或删除观察者的功能。同时,它是负责在发生任何更改时更新观察者的类。在我们的解决方案中,我们实现了ASubject
以达到相同的目的。ConcreteSubject
:此类是实现Subject
的真实类。此类是其更改会影响其他对象的实体。我们实现了DummyProject
类来实现相同的功能。Observer
:这代表一个接口,定义了每次发生更改时应调用的方法。我们将其实现为IObserver
。ConcreteObserver
:这是需要使其自身与更改保持同步的类。此类只需要实现Observer
并向ConcreteSubject
注册,就可以接收更新了。在我们的应用程序中,Shop
类充当相同的目的。
所以让我再次展示上面显示的相同图表,用于我的实现

在查看代码之前,我还有一件事想说。在 .NET 中,我们有委托,实际上是观察者模式的一个很好的例子。因此,实际上我们不需要在 C# 中完全实现该模式,因为我们可以使用委托来实现相同的功能,但我们在这里这样做是为了理解该模式。此外,我们还实现了使用委托实现观察者模式的方法。现在让我们看看代码。
主题:ASubject
abstract class ASubject
{
//This is the one way we can implement it, lets call it WAY_1
ArrayList list = new ArrayList();
//This is another way we can implement observer, lets call it WAY_2
public delegate void StatusUpdate(float price);
public event StatusUpdate OnStatusUpdate = null;
public void Attach(Shop product)
{
//For way 1 lets assign attach the observers with subjects
list.Add(product);
}
public void Detach(Shop product)
{
//For way 1 lets assign detach the observers with subjects
list.Remove(product);
}
public void Attach2(Shop product)
{
//For way 2 lets assign attach the observers with subjects
OnStatusUpdate += new StatusUpdate(product.Update);
}
public void Detach2(Shop product)
{
//For way 2 lets assign detach the observers with subjects
OnStatusUpdate -= new StatusUpdate(product.Update);
}
public void Notify(float price)
{
//For way 1 lets notify the observers with change
foreach (Shop p in list)
{
p.Update(price);
}
//For way 2 lets notify the observers with change
if (OnStatusUpdate != null)
{
OnStatusUpdate(price);
}
}
}
具体主题:DummyProduct
class DummyProduct : ASubject
{
public void ChangePrice(float price)
{
Notify(price);
}
}
观察者:IObserver
interface IObserver
{
void Update(float price);
}
具体观察者:Shop
class Shop : IObserver
{
//Name if the product
string name;
float price = 0.0f; //default
public Shop(string name)
{
this.name = name;
}
#region IObserver Members
public void Update(float price)
{
this.price = price;
//Lets print on console just to test the working
Console.WriteLine(@"Price at {0} is now {1}", name, price);
}
#endregion
}
测试代码
static void Main(string[] args)
{
DummyProduct product = new DummyProduct();
// We have four shops wanting to keep updated price set by product owner
Shop shop1 = new Shop("Shop 1");
Shop shop2 = new Shop("Shop 2");
Shop shop3 = new Shop("Shop 3");
Shop shop4 = new Shop("Shop 4");
//Lets use WAY_1 for first two shops
product.Attach(shop1);
product.Attach(shop2);
//Lets use WAY_2 for other two shops
product.Attach2(shop3);
product.Attach2(shop4);
//Now lets try changing the products price, this should update the shops automatically
product.ChangePrice(23.0f);
//Now shop2 and shop 4 are not interested in new prices so they unsubscribe
product.Detach(shop2);
product.Detach2(shop4);
//Now lets try changing the products price again
product.ChangePrice(26.0f);
Console.Read();
}
关注点
Windows Forms 编程和 MPF 应用程序的核心是观察者模式。由于事件驱动机制只能通过实现观察者模式来实现,我写了一篇非常基础的,也许对那些已经了解相关知识的人来说“不太有用”的文章,但我很享受学习和写作的过程。我的下一步是在 C++ 中实现相同的功能(使用指针、向量、迭代器和其他好东西)。
历史
- 2012 年 2 月 10 日:C# 中观察者模式的简单而基础的实现