一、定义:
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。此种模式通常被用来实时事件处理系统。其中两个重要对象是观察者和主题,要想主题对象发生改变时,能通知到所有观察者角色,则自然主题角色必须引用观察者,从而完成观察模式。
特点:
1、定义了一对多的关系。
2、主题用一个共同的接口来更新观察者。
3、观察者和主题用松耦合的方式结合,不需要知道实现细节,只需要实现接口就可以。
二、UML类图:

三、基本代码:
class Program
{
static void Main(string[] args)
{
ConcreteSubject cs = new ConcreteSubject();
cs.Attach(new ConcreteObserver(cs, "x"));
cs.Attach(new ConcreteObserver(cs, "y"));
cs.SubjectState = "abc";
cs.Notify();
Console.Read();
}
}
abstract class Subject
{
private IList<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 ob in observers)
{
ob.Update();
}
}
}
class ConcreteSubject : Subject
{
private string subjectState;
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
abstract class Observer
{
public abstract void Update();
}
class ConcreteObserver : Observer
{
private string name;
private string observerState;
private ConcreteSubject subject;
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
public ConcreteObserver(ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}
public override void Update()
{
observerState = subject.SubjectState;
Console.WriteLine("观察者{0}的新状态是{1}", name, observerState);
}
}
class Program
{
static void Main(string[] args)
{
ConcreteSubject cs = new ConcreteSubject();
cs.Attach(new ConcreteObserver(cs, "x"));
cs.Attach(new ConcreteObserver(cs, "y"));
cs.SubjectState = "abc";
cs.Notify();
Console.Read();
}
}
abstract class Subject
{
private IList<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 ob in observers)
{
ob.Update();
}
}
}
class ConcreteSubject : Subject
{
private string subjectState;
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
abstract class Observer
{
public abstract void Update();
}
class ConcreteObserver : Observer
{
private string name;
private string observerState;
private ConcreteSubject subject;
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
public ConcreteObserver(ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}
public override void Update()
{
observerState = subject.SubjectState;
Console.WriteLine("观察者{0}的新状态是{1}", name, observerState);
}
}
四、适用场景:
当一个对象的改变需要同时改变其他对象时,而且不知道具体有多少对象有待改变时,应该考虑使用观察者模式。
举例说明:

实例代码:
interface ISubject
{
void Attach(Observer observer);
void Detach(Observer observer);
void Notify();
string SubjectState { get; set; }
}
class Boss : ISubject
{
private IList<Observer> observers = new List<Observer>();
private string bossAction;
public string SubjectState
{
get { return bossAction; }
set { bossAction = value; }
}
public void Attach(Observer observer)
{
observers.Add(observer);
}
public void Detach(Observer observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer ob in observers)
{
ob.Update();
}
}
}
abstract class Observer
{
protected string name;
protected ISubject subject;
public Observer(string name, ISubject subject)
{
this.name = name;
this.subject = subject;
}
public abstract void Update();
}
class StockObserver : Observer
{
public StockObserver (string name,ISubject subject):base(name,subject )
{}
public override void Update()
{
Console.WriteLine("{0},{1} 关闭股票,继续工作", subject.SubjectState, name);
}
}
class NBAObserver : Observer
{
public NBAObserver (string name,ISubject subject):base(name,subject)
{}
public override void Update()
{
Console.WriteLine("{0},{1} 关闭NBA,继续工作", subject.SubjectState, name);
}
}
Boss boss = new Boss();
Observer s1 = new StockObserver("张三", boss);
Observer s2 = new NBAObserver("李四", boss);
boss.Attach(s1);
boss.Attach(s2);
boss.SubjectState = "老板回来了";
boss.Notify();
五、观察者模式的缺点及解决方法:
在具体前台、同事和老板的实例中,使用依赖倒转原则,但是“抽象通知者”还是依赖“抽象观察者”,即如果没有抽象观察者这样的接口,通知功能就完不成。另外就是每个具体观察者,它不一定是“更新”的方法要调用,可能是其他的方法。解决方法:通知者和观察者之间根本互相不知道,由客户端决定通知谁。对于前台的实例,决定使用委托的方式来实现由客户端来决定具体通知谁的功能。
实例说明:
interface ISubject
{
void Attach(Observer observer);
void Detach(Observer observer);
void Notify();
string SubjectState { get; set; }
}
class Boss : ISubject
{
private IList<Observer> observers = new List<Observer>();
private string bossAction;
public string SubjectState
{
get { return bossAction; }
set { bossAction = value; }
}
public void Attach(Observer observer)
{
observers.Add(observer);
}
public void Detach(Observer observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer ob in observers)
{
ob.Update();
}
}
}
abstract class Observer
{
protected string name;
protected ISubject subject;
public Observer(string name, ISubject subject)
{
this.name = name;
this.subject = subject;
}
public abstract void Update();
}
class StockObserver : Observer
{
public StockObserver (string name,ISubject subject):base(name,subject )
{}
public override void Update()
{
Console.WriteLine("{0},{1} 关闭股票,继续工作", subject.SubjectState, name);
}
}
class NBAObserver : Observer
{
public NBAObserver (string name,ISubject subject):base(name,subject)
{}
public override void Update()
{
Console.WriteLine("{0},{1} 关闭NBA,继续工作", subject.SubjectState, name);
}
}
interface ISubject
{
void Notify();
string SubjectState { get; set; }
}
public delegate void DelegateHandler();
class Boss : ISubject
{
public event DelegateHandler Update;
public string SubjectState { get; set; }
public void Notify()
{
Update();
}
}
abstract class Observer
{
protected string name;
protected ISubject subject;
public Observer(string name, ISubject subject)
{
this.name = name;
this.subject = subject;
}
public abstract void Update();
}
class StockObserver : Observer
{
public StockObserver(string name, ISubject subject)
: base(name, subject)
{ }
public override void Update()
{
Console.WriteLine("{0},{1} 关闭股票,继续工作", subject.SubjectState, name);
}
}
class NBAObserver : Observer
{
public NBAObserver(string name, ISubject subject)
: base(name, subject)
{ }
public override void Update()
{
Console.WriteLine("{0},{1} 关闭NBA,继续工作", subject.SubjectState, name);
}
}
Boss boss = new Boss();
StockObserver s1 = new StockObserver("张三", boss);
NBAObserver s2 = new NBAObserver("李四", boss);
boss.Update += new DelegateHandler(s1.Update);
boss.Update += new DelegateHandler(s2.Update);
boss.SubjectState = "老板回来了";
boss.Notify();
六、总结:
观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体,从而使各自的变化都不会影响到另一边的变化。
