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

观察者模式 (C#)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (38投票s)

2014年5月6日

CPOL

4分钟阅读

viewsIcon

164631

在 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 日)
© . All rights reserved.