模式定义
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
UML类图
- 观察目标(Subject) 也称被观察的对象,有观察者类型集合字段,并提供订阅
Attach(Observer observer)
和取消订阅方法Detach(Observer observer)
,以及通知观察者方法Notify()
。 - 具体观察目标(ConcreteSubject) 目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,调用通知方法。
- 观察者(Observer) 定义对观察目标的改变做出操作
Update()
抽象方法 - 具体观察者(ConcreteObserver) 实现抽象观察者角色接口,(如果需要目标类更多信息,则需要依赖具体目标类)
代码结构
public class ObserverApp
{
public void Run()
{
ConcreteSubject s = new ConcreteSubject();
s.Attach(new ConcreteObserver() { Subject = s, Name = "X" });
s.Attach(new ConcreteObserver() { Subject = s, Name = "Y" });
s.Attach(new ConcreteObserver() { Subject = s, Name = "Z" });
s.SubjectState = "ABC";
s.Notify();
}
}
abstract class Subject
{
private List<Observer> _observers = new List<Observer>();
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();
}
}
}
class ConcreteSubject : Subject
{
public string SubjectState { get; set; }
}
abstract class Observer
{
public abstract void Update();
}
class ConcreteObserver : Observer
{
public string Name { get; set; }
public ConcreteSubject Subject { get; set; }
public override void Update()
{
string state = this.Subject.SubjectState;
Console.WriteLine("Observer {0}'s new state is {1}",this.Name,state);
}
}
情景案例
现在大家最关心的应该是回家过年的火车票,相信大家电脑上也安装了些刷票的软件吧!这样才能安心工作,等有票了自动通知。
public class ObserverApp
{
public void Run()
{
Ticket360 s = new Ticket360();
s.Attach(new ConcreteCustomer() { Subject = s, Name = "小王" });
s.Attach(new ConcreteCustomer() { Subject = s, Name = "小赵" });
s.Attach(new ConcreteCustomer() { Subject = s, Name = "小孙" });
s.TicketState = "有坐票";
s.Notify();
}
}
/// <summary>
/// 火车票
/// </summary>
abstract class Ticket
{
private List<Customer> _observers = new List<Customer>();
public void Attach(Customer observer)
{
_observers.Add(observer);
}
public void Detach(Customer observer)
{
_observers.Remove(observer);
}
public void Notify()
{
foreach (Customer o in _observers)
{
o.Notify();
}
}
}
class Ticket360 : Ticket
{
public string TicketState { get; set; }
}
abstract class Customer
{
public abstract void Notify();
}
class ConcreteCustomer : Customer
{
public string Name { get; set; }
public Ticket360 Subject { get; set; }
public override void Notify()
{
string state = this.Subject.TicketState;
Console.WriteLine("{0}顾客关注的火车票现在状态为 {1}", this.Name, state);
}
}
C#中的优化
在C#中其实可以通过delegate
和Event
,可参数传递函数,更方便的实现观察者模式。