设计模式涵义
设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案。面向对象设计模式描述了面向对象设计过程中、特定场景下、类与相互通信的对象之间常见的组织关系。
观察者模式定义
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新.
uml类图
![](https://images.cnblogs.com/cnblogs_com/marvel/observer.gif)
参与者
- Subject(股票)
- 知道它的Observer,所有的Observer都可能观察此对象
- 提供了一个附加和分离Observer的接口
- ConcreteSubject(ibm的股票)
- 保存Observer感兴趣的状态
- 当状态发生变化时.通知Observer
- Observer(股东)
- 为这些要接受通知的ConcreteObserver定义一个更新的接口
- ConcreteObserver(股东)
- 维持对concretesubject的引用
- 存储状态并与Subject的状态保持一致
- 实现observer的更新接口以保持与Subject的状态一致
c#样例
结构性代码演示了当状态发生变化时,将通知和更新注册在Observer模式下的对象.
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
using System;
using System.Collections;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace DoFactory.GangOfFour.Observer.Structural
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// MainApp test application
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
class MainApp
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
static void Main()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// Configure Observer pattern
ConcreteSubject s = new ConcreteSubject();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
s.Attach(new ConcreteObserver(s,"X"));
s.Attach(new ConcreteObserver(s,"Y"));
s.Attach(new ConcreteObserver(s,"Z"));
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Change subject and notify observers
s.SubjectState = "ABC";
s.Notify();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Wait for user
Console.Read();
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// "Subject"
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
abstract class Subject
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private ArrayList observers = new ArrayList();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void Attach(Observer observer)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
observers.Add(observer);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void Detach(Observer observer)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
observers.Remove(observer);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void Notify()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
foreach (Observer o in observers)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
o.Update();
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// "ConcreteSubject"
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
class ConcreteSubject : Subject
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private string subjectState;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Property
public string SubjectState
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return subjectState; }
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ subjectState = value; }
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// "Observer"
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
abstract class Observer
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public abstract void Update();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// "ConcreteObserver"
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
class ConcreteObserver : Observer
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private string name;
private string observerState;
private ConcreteSubject subject;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Constructor
public ConcreteObserver(
ConcreteSubject subject, string name)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.subject = subject;
this.name = name;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public override void Update()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
observerState = subject.SubjectState;
Console.WriteLine("Observer {0}'s new state is {1}",
name, observerState);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Property
public ConcreteSubject Subject
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return subject; }
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ subject = value; }
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
Output
Observer X's new state is ABC
Observer Y's new state is ABC
Observer Z's new state is ABC
实例代码演示了当股票发生变化时.将会通知股东(投资人).
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Observer.RealWorld
{
// MainApp test application
class MainApp
{
static void Main()
{
// 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;
// Wait for user
Console.Read();
}
}
// "Subject"
abstract class Stock
{
protected string symbol;
protected double price;
private ArrayList investors = new ArrayList();
// Constructor
public Stock(string symbol, double price)
{
this.symbol = symbol;
this.price = price;
}
public void Attach(Investor investor)
{
investors.Add(investor);
}
public void Detach(Investor investor)
{
investors.Remove(investor);
}
public void Notify()
{
foreach (Investor investor in investors)
{
investor.Update(this);
}
Console.WriteLine("");
}
// 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
{
void Update(Stock stock);
}
// "ConcreteObserver"
class Investor : IInvestor
{
private string name;
private Stock stock;
// Constructor
public Investor(string name)
{
this.name = name;
}
public void Update(Stock stock)
{
Console.WriteLine("Notified {0} of {1}'s " +
"change to {2:C}", name, stock.Symbol, stock.Price);
}
// Property
public Stock Stock
{
get{ return stock; }
set{ stock = value; }
}
}
}
Output
Notified Sorros of IBM's change to $120.10
Notified Berkshire of IBM's change to $120.10
Notified Sorros of IBM's change to $121.00
Notified Berkshire of IBM's change to $121.00
Notified Sorros of IBM's change to $120.50
Notified Berkshire of IBM's change to $120.50
Notified Sorros of IBM's change to $120.75
Notified Berkshire of IBM's change to $120.75
,