当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
在现实生活中,处处可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用。
先定义一个观察者
interface Observer
{
void Update(string message);
}
再定义一个被观察者
interface Subject
{
void RegisterObserver(Observer ob);
void RemoveObserver(Observer ob);
void NotifyObserver();
}
实现这个被观察者MySubject 类
class MySubject : Subject
{
private List<Observer> observers = new List<Observer>();
private string info;
public void NotifyObserver()
{
for (int i=0; i<observers.Count; i++)
{
Observer ob = observers[i];
ob.Update(info);
}
}
public void RegisterObserver(Observer ob)
{
observers.Add(ob);
}
public void RemoveObserver(Observer ob)
{
int i = observers.IndexOf(ob);
if (i >= 0)
{
observers.Remove(ob);
}
}
public void SetInfo(string message)
{
this.info = message;
this.NotifyObserver();
}
}
再实现这个观察者,用了两个实体类FirstObserver类与SecondObserver类
class FirstObserver : Observer
{
public void Update(string message)
{
Console.WriteLine("第一个观察者:{0}", message);
}
}
class SecondObserver : Observer
{
public void Update(string message)
{
Console.WriteLine("第二个观察者:{0}", message);
}
}
调用
class Program
{
static void Main(string[] args)
{
MySubject subject = new MySubject();
FirstObserver firstObserver = new FirstObserver();
SecondObserver secondObserver = new SecondObserver();
subject.RegisterObserver(firstObserver);
subject.RegisterObserver(secondObserver);
subject.SetInfo("111");
subject.SetInfo("222");
subject.SetInfo("333");
Console.Read();
}
}
结果
第一个观察者:111
第二个观察者:111
第一个观察者:222
第二个观察者:222
第一个观察者:333
第二个观察者:333
类图
优点与缺点
观察者模式的优点:
- 观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者。
- 观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。
- 观察者模式支持广播通信。被观察者会向所有的注册过的观察者发出通知。
观察者模式的缺点:
- 如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
- 虽然观察者模式可以随时使观察者知道所观察的对象发送了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎样发生变化的。
- 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,在使用观察者模式应特别注意这点。
本文主要借鉴了《Gof设计模式》