`
阅读更多

观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

 

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.
这个主题对象在状态上发生变化时,会通知所有观察者对象,让他们能够自动更新自己。

一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设计方案中最重要的一种。

 

使用场合:
1) 当一个抽象模型,其中一个方面依赖于另一个方面,把这两者封装在独立的对象中,使其
可以独立的改变和复用.(比如:一个男孩依赖于一个女孩,当女孩发生变化的时候,他也发生了变化)
2) 改变一个对象需要同时改变其它对象,但不知道又多少对象有待于改变.
(比如:多个男孩喜欢一个女孩,但是她不知道有多少个男孩喜欢自己)
3)  一个对象必须通知其它对象,但又不能假定这些对象(也就是这些对象是松耦合的,低耦合度的设计方案。减少对象之间的耦合有利于系统的复用),
(比如数据采集模块,当采集到数据以后,必须通知其他对象,但在开发采集模块的时候,事先
并不知道其它对象是什么)

 

观察者模式的组成:
抽象主题(Subject)角色:把所有对观察着对象的引用保存在一个集合(聚集)中,每个抽象主题角色都可以有任意数量的
观察者.抽象主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现.
(抽象主题角色主要是用来操作,可以增加和删除观察者角色.由它的子类实现)

 

抽象观察者(Observer)角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己.这个接口叫做更新接口.
抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法.

 

具体主题(ConcreteSubject)角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知.

具体主题角色又叫做具体被观察者角色(Concrete Observable).具体主题角色通常用一个
子类实现.

 

具体观察者(ConcreteObserver)角色:该角色实现抽象观察者角色所要更新的接口,以便使本身的状态与主题的状态相协调.如果需要,具体观察者角色可以保存一个指向具体主题角色的引用,通常用一个子类实现.

 

 

从具体主题角色指向抽象观察者角色的合成关系,代表具体主题对象可以有任意多个对抽象观察者对象的引用.之所以使用抽象观察者而不是具体观察者,意味着主题对象不需要知道引用了哪些ConcreteObserver类型,而只知道抽象Observer类型.这就使得具体主题对象可以动态地维护一系列的对观察者对象的引用,并在需要的时候调用每一个观察者共有的Update()方法.这种做法叫做"针对抽象编程".

ClassDiagram:

 

 

 

SequenceDiagram:

 

 

  class Client
    {
        static void Main(string[] args)
        {
            ConcreteSubject concreteSubject = new ConcreteSubject();
            concreteSubject.Attech(new ConcreteObserver(concreteSubject,"1"));
            concreteSubject.Attech(new ConcreteObserver(concreteSubject,"2"));
            concreteSubject.Attech(new ConcreteObserver(concreteSubject,"3"));
            concreteSubject.SubjectState = "OK";
            concreteSubject.Notifly();
            Console.ReadKey();
        }
    }

    /// <summary>
    /// 抽象主题
    /// </summary>
    abstract class Subject
    {
        private ArrayList observers = new ArrayList();

        public void Attech(Observer observer)
        {
            observers.Add(observer);
        }

        public void Detach(Observer observer)
        {
            observers.Add(observer);
        }

        public void Notifly()
        {
            foreach (Observer observer in observers)
            {
                observer.Update();
            }
        }
    }

    /// <summary>
    /// 抽象观察者
    /// </summary>
    abstract class Observer
    {
        abstract public void Update();
    }

    /// <summary>
    /// 具体的主题
    /// </summary>
    class ConcreteSubject : Subject
    {
        private String subjectState;

        public String SubjectState
        {
            get { return subjectState; }
            set { subjectState = value; }
        }


    }

    /// <summary>
    /// 具体观察者
    /// </summary>
    class ConcreteObserver : Observer
    {
        private string name;
        private string observerState;
        private ConcreteSubject subject;

        public ConcreteObserver(ConcreteSubject subject, string name)
        {
            this.subject = subject;
            this.name = name;
        }

        public override void Update()
        {
            observerState = subject.SubjectState;
            Console.WriteLine("Observer{0}'s new state is {1}", name, observerState);
        }

        public ConcreteSubject Subject
        {
            get { return subject; }
            set { subject = value; }
        }
    }

 

NET中提供了Delegate与Event机制,我们可以利用这种机制简化Observer模式。

 

using System;

//Delegate
delegate void UpdateDelegate(); 

//Subject
class Subject
{
  public event UpdateDelegate UpdateHandler;
  
  // Methods
  public void Attach( UpdateDelegate ud )
  {
    UpdateHandler += ud;
  }

  public void Detach( UpdateDelegate ud )
  {
    UpdateHandler -= ud;
  }
  
  public void Notify()
  {
    if(UpdateHandler != null) UpdateHandler();
  }

}

//ConcreteSubject
class ConcreteSubject : Subject
{
  // Fields
  private string subjectState;

  // Properties
  public string SubjectState
  {
    get{ return subjectState; }
    set{ subjectState = value; }
  }
}

// "ConcreteObserver"
class ConcreteObserver
{
  // Fields
  private string name;
  private string observerState;
  private ConcreteSubject subject;

  // Constructors
  public ConcreteObserver( ConcreteSubject subject,  
    string name )
  {
    this.subject = subject;
    this.name = name;
  }

  // Methods
  public void Update()
  {
    observerState = subject.SubjectState;
    Console.WriteLine( "Observer {0}'s new state is {1}",
      name, observerState );
  }

  // Properties
  public ConcreteSubject Subject
  {
    get { return subject; }
    set { subject = value; }
  }
}

// "ConcreteObserver"
class AnotherObserver
{
  // Methods
  public void Show()
  {
    Console.WriteLine("AnotherObserver got an Notification!");
  }
}

public class Client
{ 
  public static void Main(string[] args)
  { 
    ConcreteSubject s = new ConcreteSubject();
    ConcreteObserver o1 = new ConcreteObserver(s, "1");
    ConcreteObserver o2 = new ConcreteObserver(s, "2");
    AnotherObserver o3 = new AnotherObserver();
    
    s.Attach(new UpdateDelegate(o1.Update));
    s.Attach(new UpdateDelegate(o2.Update));
    s.Attach(new UpdateDelegate(o3.Show));

    s.SubjectState = "ABC";
    s.Notify();

    Console.WriteLine("--------------------------");
    s.Detach(new UpdateDelegate(o1.Update));

    s.SubjectState = "DEF";
    s.Notify();
  }
}

  

    其中,关键的代码如下:

 

delegate void UpdateDelegate(); 

   

定义一个Delegate,用来规范函数结构。不管是ConcreteObserver类的Update方法还是AnotherObserver类的Show方法都符合该Delegate。这不象用Observer接口来规范必须使用Update方法那么严格。只要符合Delegate所指定的方法结构的方法都可以在后面被事件所处理。

 

public event UpdateDelegate UpdateHandler;

 

定义一个事件,一旦触发,可以调用一组符合UpdateDelegate规范的方法。

 

public void Attach( UpdateDelegate ud )
  {
    UpdateHandler += ud;
  }

 

订阅事件。只要是一个满足UpdateDelegate的方法,就可以进行订阅操作(如下所示)。

 

    s.Attach(new UpdateDelegate(o1.Update));
    s.Attach(new UpdateDelegate(o2.Update));
    s.Attach(new UpdateDelegate(o3.Show));

 

在Notify方法中:

 

public void Notify()
  {
    if(UpdateHandler != null)
         UpdateHandler();
  }

  

只要UpdateHandler != null(表示有订阅者),就可以触发事件(UpdateHandler()),所有的订阅者便会接到通知。

 

该例子演示了注册的投资者在股票市场发生变化时,可以自动得到通知。该例子仍然使用的是传统的Observer处理手段,至于如何转换成Delegate与Event留给读者自己考虑。

 

  class Client
    {
        static void Main(string[] args)
        {
            //张三李四两个观察者,他们都关注IBM这支股票
            Investor investor1 = new Investor("张三");
            Investor investor2 = new Investor("李四");
            IBM ibm = new IBM("IBM",120);
            ibm.Attach(investor1);
            ibm.Attach(investor2);
            ibm.Price = 120.10;
            ibm.Price = 120.22;
            Console.ReadKey();
        }
    }

    /// <summary>
    /// 股票
    /// </summary>
    abstract class Stock
    {
        protected string symbol;
        protected double price;
        private ArrayList investors = new ArrayList();

        public Stock(String symbol, double price)
        {
            this.symbol = symbol;
            this.price = price;
        }

        public void Attach(Iinvestor investor)
        {
            investors.Add(investor);
        }

        public void Dteach(Iinvestor investor)
        {
            investors.Remove(investor);
        }

        public void Notify()
        {
            foreach (Iinvestor investor in investors)
            {
                investor.Update(this);
            }
        }

        public double Price
        {
            get
            {
                return price;
            }
            set
            {
                price = value;
                Notify();
            }
        }

        public string Symbol
        {
            get { return symbol; }
            set { symbol = value; }
        }
    }

    class IBM : Stock
    {
        public IBM(string symbol, double price) : base(symbol, price) { }

    }

    interface Iinvestor
    {
        void Update(Stock stock);
    }

    /// <summary>
    /// 投资者
    /// </summary>
    class Investor : Iinvestor
    {
        private string name;
        private string observerState;

        public string ObserverState
        {
            get { return observerState; }
            set { observerState = value; }
        }

        
        public Investor(string name)
        {
            this.name = name;
        }

        public void Update(Stock stock)
        {
            Console.WriteLine("Notified investor {0} of {1}'s change to{2:c}",name,stock.Symbol,stock.Price);
        }
    }

 

Observer模式的优点是实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,类别清晰,并抽象了更新接口,使得可以有各种各样不同的表示层(观察者)。

但是其缺点是每个外观对象必须继承这个抽像出来的接口类,这样就造成了一些不方便,比如有一个别人写的外观对象,并没有继承该抽象类,或者接口不对,我们又希望不修改该类直接使用它。虽然可以再应用Adapter模式来一定程度上解决这个问题,但是会造成更加复杂烦琐的设计,增加出错几率。

 

观察者模式的效果有以下几个优点:

(1)观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。

 

(2)观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。

观察者模式有下面的一些缺点:

 

(1)如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

 

(2)如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。

 

(3)如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

 

(4)虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

  • 大小: 38 KB
  • 大小: 19.2 KB
分享到:
评论

相关推荐

    详解Observer Pattern(观察者模式)在Java中的使用原理

    我们说学习Java应该从Swing开始,那么学习Swing最重要的思想就是对于观察者模式的理解(Observer Pattern)。因为,该设计模式在Java Swing框架中贯穿了始终。对于C#的委托、代理概念所使用的Callback(回调模式--...

    设计模式之观察者模式(Observer Pattern)

    "ObserverPattern(订阅模式)3.zip"中的代码可能进一步阐述了观察者模式,这里的“订阅”一词可能意味着用户可以订阅特定的主题,只有当这些主题的状态改变时,用户才会收到通知。这与传统的观察者模式类似,但更加...

    Observer Pattern.rar

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件驱动的系统...

    ObserverPattern.zip

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在这个例子中,李先生是观察者,他希望得到气象站的天气预报更新和旅行社的...

    matlab开发-Observerpattern

    观察者模式(Observer Pattern)是设计模式中的一种行为模式,它允许一个对象,当其状态发生改变时,能够自动通知所有依赖它的对象。在MATLAB中实现观察者模式,可以帮助我们构建灵活、可扩展的代码结构,特别是在...

    Observer Pattern Example.rar

    观察者模式(Observer Pattern)是软件设计模式中的行为模式之一,其主要思想是定义一个一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式在软件开发中,尤其是...

    ObserverPattern.unitypackage

    ObserverPattern.unitypackage是一个以unity为例写的观察者模式的应用举例。有需要的同学请下载!

    类似 Observer Pattern 的 NSNotificationCenter (实例)

    【标题】:“类似 Observer Pattern 的 NSNotificationCenter(实例)” 在iOS和macOS开发中,`NSNotificationCenter` 是一个关键的组件,它实现了一种类似于观察者模式(Observer Pattern)的机制。观察者模式是一...

    swift-Swiftµframework实现观察者模式Observerpattern

    Swift µframework 实现观察者模式Observer pattern

    观察者模式(Observer Pattern) 1. 什么是观察者模式? 2. 为什么需要观察者模式? 3. 观察者模式的核心概念 4. 观察者模式的结构 5. 观察者模式的基本实现 简单的气象站示例

    观察者模式(Observer Pattern) 1. 什么是观察者模式? 2. 为什么需要观察者模式? 3. 观察者模式的核心概念 4. 观察者模式的结构 5. 观察者模式的基本实现 简单的气象站示例 6. 观察者模式的进阶实现 推模型 vs 拉...

    ObserverPattern2-Code5.zip

    这是关于C#中的观察者模式的教程文章。我们首先介绍作为GoF模式之一的经典观察者模式。观察者模式通过使用事件机制集成到C#中,这将在接下来讨论。然后,我们讨论与在C#中使用事件/事件处理程序相关的问题。

    设计模式- 观察者模式 Observer Pattern详解

    首先,观察者模式的经典实现涉及两个主要对象:主题(Subject)和观察者(Observer)。主题维护一组观察者,并在状态变化时通知它们。观察者则订阅主题,以便在主题状态改变时接收通知。在C#中,这通常通过接口来...

    observer-pattern:New's Station Observer Pattern演示

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在Java中,这种模式通常通过实现`java.util.Observable`接口和`java.util....

    C#设计模式(17)——观察者模式(Observer Pattern).pdf

    从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户。从中,我们就可以得出观察者模式的定义。  观察者模式定义了一种一对多的依赖关系,让多个观察者对象...

    C#观察者模式(Observer Pattern)实例教程

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在C#中,这种模式经常用于事件处理,使得对象之间可以松散耦合地交互。下面...

    JavaScript编程设计模式之观察者模式(Observer Pattern)实例详解

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它允许对象在状态改变时通知其他对象,而这些对象可能会对这种变化做出响应。在JavaScript中,观察者模式常用于事件驱动编程,例如DOM事件处理、用户...

Global site tag (gtag.js) - Google Analytics