观察者模式
使用思路:订阅者与发布者,发布者改动后通知订阅者。适合一处变动多处响应的场景。
例子
建议先看一下李会军老师的例子
http://www.cnblogs.com/Terrylee/archive/2006/10/23/Observer_Pattern.html
例子包含了观察者代码的演变过程。
以下是本书的例子(C#3.0设计模式)
using System;
using System.Collections;
using System.Threading;
class ObserverPattern
{
//Observer Pattern Judith Bishop Jan 2007
// The Subject runs in a thread and changes its state
// independently. At each change, it notifies its Observers.
class Subject
{
public delegate void Callback(string s);
public event Callback Notify;
Simulator simulator = new Simulator();
const int speed = 200;
public string SubjectState { get; set; }
public void Go()
{
new Thread(new ThreadStart(Run)).Start();
}
void Run()
{
foreach (string s in simulator)
{
Console.WriteLine("Subject: " + s);
SubjectState = s;
Notify(s);
Thread.Sleep(speed); //millisconds
}
}
}
interface IObserver
{
void Update(string state);
}
class Observer : IObserver
{
string name;
Subject subject;
string state;
string gap;
public Observer(Subject subject, string name, string gap)
{
this.subject = subject;
this.name = name;
this.gap = gap;
subject.Notify += Update;
}
public void Update(string subjectState)
{
state = subjectState;
Console.WriteLine(gap + name + ": " + state);
}
}
static void Main()
{
Subject subject = new Subject();
Observer Observer = new Observer(subject, "Center", "\t\t");
Observer observer2 = new Observer(subject, "Right", "\t\t\t\t");
subject.Go();
Console.ReadKey();
}
class Simulator : IEnumerable
{
string[] moves = { "5", "3", "1", "6", "7" };
public IEnumerator GetEnumerator()
{
foreach (string element in moves)
yield return element;
}
}
}
/*Output
Subject: 5
Center: 5
Right: 5
Subject: 3
Center: 3
Right: 3
Subject: 1
Center: 1
Right: 1
Subject: 6
Center: 6
Right: 6
*/
由李会军老师的代码演变过程得知,Subject与Observer是互相调用的关系。
到本书代码的时候,已经进化为Subject代码内没有任何Observer的影子,仅保留一个事件委托。
如果将 subject.Notify += Update; 脱离出Observer,由客户端来操作的话,则Observer内也完全脱离Subject。真正实现针对接口编程。