这篇文章距离最后更新已过89 天,如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
定义
- 又叫 发布-订阅 模式
- 定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
- 这个主题对象的状态发生变化时,会通知所有的观察者对象,使它们自己能够更新自己
- 观察者所做的工作就是在解除耦合,让耦合的双方都依赖于抽象,而不依赖于具体,从而使得各自变化不会影响到另一边
使用场景
- 关联行为场景,当一个对象发生改变时,需要同时改变其他对象
- 事件多级触发场景
- 跨系统的消息变换场景
举例
- 手机丢了,委托别人发消息
- 通知老板来了
- 拍卖,拍卖师观察最高价,并同时通知其他竞价者竞价
- 在一个目录下建立一个文件,会同时通知目录管理器增加目录,并通知磁盘减少空间,文件是被观察者,目录管理器和磁盘管理器是观察者
- 猫叫了一声,吓着了老鼠,也惊到了主人,猫是被观察者,老鼠和人是观察者
代码实现
//抽象主题类 通知类
abstract class Subject
{
private IList<ObServer> observers = new List<Observer>();
private void Attach(Observer observer)
{
observers.Add(observer);
}
public void Detach(Observer observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach(var item in observers)
{
item.Update();
}
}
}
//抽象的观察者类
abstract class Observer
{
public abstract void Update();
}
//具体通知类
class ConcreteSubject: Subject
{
public string SubjectState{ get; set; }
}
//具体观察者类
class ConcreteObserver: Observer
{
private string name;
private string observerState;
private ConcreteSubject subject;
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);
}
public ConcreteSubject Subject { get { return subject; } set { subject = value; } }
}
void Main()
{
ConcreteSubject s = new ConcreteSubject();
s.Attach(new ConcreteObserver(s,"A"));
s.Attach(new ConcreteObserver(s,"B"));
s.Attach(new ConcreteObserver(s,"C"));
s.SubjectState = "MS";
s.Notify();
}
优点
- 观察者和被观察者是抽象耦合的
- 建立了一套触发机制
缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有观察者通知会花费很多时间
- 如果观察者和观察目标间有循环依赖,将会导致崩溃
- 没有相应的机制让观察者知道观察的目标是如何变化的