观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
举个简单的例子:
报纸和杂志的订阅。
- 报社的业务就是出版报纸
- 向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,就会一直收到报纸。
- 当你不想再看报纸时,取消订阅,他们就不会再送新的报纸来。
- 只要报社还在运营,就会一直有人(或单位)向他们订阅或取消订阅报纸。
出版者(主题subject)+订阅者(观察者observer)=观察者模式
看下面的实例,讨论观察者模式的结构:
抽象主题:
public Interface Subject
{
//注册观察者
void registerObserver(Observer o);
//移出观察者
void removeObserver(Observer o);
//更新观察者数据
void notifyObserver();
}
抽象观察者:
public instrface Observer
{
//更新数据
void update();
}
具体主题:
public class ConcreteSubject:Subject
{
//观察者集合
private List<Observer> observers;
public ConcreteSubject()
{
observers = new List<Observer>();
}
public void registerObserver(Observer o)
{
//添加观察者
observers.add(o);
}
public void removeObserver(Observer o)
{
//移出观察者
observers.remove(o);
}
public void notifyObserver()
{
//更新观察者数据
for(int i=0;i<observers.count;i++)
{
Observer observer=(Observer)observers.get(i);
observer.update();
}
}
}
具体观察者:
public class ConcreteObserver:Observer
{
private Subject _subject;
public ConcreteObserver(Subject subject)
{
_subject=subject;
//调用注册方法
_subject.registerObserver(this);
}
public void update()
{
Console.writeLine("更新操作");
}
}
主题只知道观察者的一件事,那就是观察者实现了Observer接口。
推拉模式
“推”的优点:
上文所说的,是由主题主动对观察者进行“推”数据。这样的好处是,通过“拉”数据的方式,可能观察者需要拉很多次才能收集全它所想要的数据,但是“推”可以在一次通知中一口气得到所有的东西。
“拉”的优点:
假设每人只需要一点点数据,通过“推”的方式就会被迫收到一大堆无用的数据,占用带宽和内存。这么做同时也可以在以后比较容易修改。比方说,哪一天决定扩展功能,新增更多的状态,主题就不需要修改和更新对每位观察者的调用,只需改变自己来允许更多的getter方法来取得新增的状态。