Observer

Definition

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Frequency of use:  high

UML class diagram


Participants 
 The classes and/or objects participating in this pattern are:

  • Subject  (Stock)
    • knows its observers. Any number of Observer objects may observe a subject
    • provides an interface for attaching and detaching Observer objects.
  • ConcreteSubject  (IBM)
    • stores state of interest to ConcreteObserver
    • sends a notification to its observers when its state changes
  • Observer  (IInvestor)
    • defines an updating interface for objects that should be notified of changes in a subject.
  • ConcreteObserver  (Investor)
    • maintains a reference to a ConcreteSubject object
    • stores state that should stay consistent with the subject's
    • implements the Observer updating interface to keep its state consistent with the subject's



Sample code in C#

This structural code demonstrates the Observer pattern in which registered objects are notified of and updated with a state change.



// Observer pattern -- Structural example

using System;
using System.Collections;

// "Subject"


abstract
class Subject

{
  // Fields
  private ArrayList observers = new ArrayList();

 
// Methods
  public void Attach( Observer observer )
  {
    observers.Add( observer );
  }

  public
void Detach( Observer observer )

  {
    observers.Remove( observer );
  }

  public
void Notify()

  {
    foreach( Observer o in observers )
      o.Update();
  }
}

// "ConcreteSubject"


class
ConcreteSubject : Subject

{
  // Fields
  private string subjectState;

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

// "Observer"


abstract
class Observer

{
  // Methods
  abstract public void Update();
}

// "ConcreteObserver"


class
ConcreteObserver : Observer

{
  // Fields
  private string name;
  private string observerState;
  private ConcreteSubject subject;

 
// Constructors
  public ConcreteObserver( ConcreteSubject subject, 
                                   string
name )

  {
    this.subject = subject;
    this.name = name;
  }

 
// Methods
  override 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; }
  }
}

///
<summary>

/// Client test
/// </summary>
public class Client
{
  public static void Main( string[] args )
  {
    // Configure Observer structure
    ConcreteSubject s = new ConcreteSubject();
    s.Attach( new ConcreteObserver( s, "X" ) );
    s.Attach( new ConcreteObserver( s, "Y" ) );
    s.Attach( new ConcreteObserver( s, "Z" ) );

   
// Change subject and notify observers
    s.SubjectState = "ABC";
    s.Notify();
  }
}

Output
Observer X's new state is ABC
Observer Y's new state is ABC
Observer Z's new state is ABC



This real-world code demonstrates the Observer pattern in which registered investors are notified every time a stock changes value.



// Observer pattern -- Real World example

using System;
using System.Collections;

// "Subject"


abstract
class Stock

{
  // Fields
  protected string symbol;
  protected double price;
  private ArrayList investors = new ArrayList();

 
// Constructor
  public Stock( string symbol, double price )
  {
    this.symbol = symbol;
    this.price = price;
  }

 
// Methods
  public void Attach( Investor investor )
  {
    investors.Add( investor );
  }

  public
void Detach( Investor investor )

  {
    investors.Remove( investor );
  }

  public
void Notify()

  {
    foreach( Investor i in investors )
      i.Update( this );
  }

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

  public
string Symbol

  {
    get{ return symbol; }
    set{ symbol = value; }
  }
}

// "ConcreteSubject"


class
IBM : Stock

{
  // Constructor
  public IBM( string symbol, double price )
                  : base( symbol, price ) {}
}

// "Observer"


interface
IInvestor

{
  // Methods
  void Update( Stock stock );
}

// "ConcreteObserver"


class
Investor : IInvestor

{
  // Fields
  private string name;
  private string observerState;
  private Stock stock;

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

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

 
// Properties
  public Stock Stock
  {
    get{ return stock; }
    set{ stock = value; }
  }
}

///
<summary>

/// ObserverApp test
/// </summary>
public class ObserverApp
{
  public static void Main( string[] args )
  {
    // Create investors
    Investor s = new Investor( "Sorros" );
    Investor b = new Investor( "Berkshire" );

   
// Create IBM stock and attach investors
    IBM ibm = new IBM( "IBM", 120.00 );
    ibm.Attach( s );
    ibm.Attach( b );

   
// Change price, which notifies investors
    ibm.Price = 120.10;
    ibm.Price = 121.00;
    ibm.Price = 120.50;
    ibm.Price = 120.75;
  }
}

Output
Notified investor Sorros of IBM's change to $120.10
Notified investor Berkshire of IBM's change to $120.10
Notified investor Sorros of IBM's change to $121.00
Notified investor Berkshire of IBM's change to $121.00
Notified investor Sorros of IBM's change to $120.50
Notified investor Berkshire of IBM's change to $120.50
Notified investor Sorros of IBM's change to $120.75
Notified investor Berkshire of IBM's change to $120.75





  <script type="text/javascript"> <!-- google_ad_client = "pub-3229461756054479"; google_ad_width = 160; google_ad_height = 600; google_ad_format = "160x600_as"; google_ad_channel =""; google_ad_type = "text"; google_color_border = "FF4500"; google_color_bg = "FFEBCD"; google_color_link = "0033CC"; google_color_url = "009900"; google_color_text = "333333"; //--> </script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-3229461756054479&dt=1111371048606&lmt=1111371048&format=160x600_as&output=html&url=http%3A%2F%2Fwww.dofactory.com%2FPatterns%2FPatternObserver.aspx&color_bg=FFEBCD&color_text=333333&color_link=0033CC&color_url=009900&color_border=FF4500&ad_type=text&ref=http%3A%2F%2Fwww.dofactory.com%2FPatterns%2FPatterns.aspx&u_h=768&u_w=1024&u_ah=715&u_aw=1024&u_cd=32&u_tz=480&u_his=1&u_java=true" frameborder="0" width="160" scrolling="no" height="600" allowtransparency="65535">


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值