65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (18投票s)

2012 年 2 月 10 日

CPOL

3分钟阅读

viewsIcon

97691

downloadIcon

1490

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# 中观察者模式的简单而基础的实现
© . All rights reserved.