观察者模式的定义:定义对象间的一种一对多的依赖关系。当一个对象(目标对象)的状态发生变化时,所有依赖于它的对象(观察者)都得到通知并被自动更新。
我们来设想一个这样的情景,我们到报社订阅报纸,那么报社就相当于目标对象,当被订阅的报纸被印刷出来时(状态发生变化),报社就会将这些报纸发送给订阅人阅读(观察者得到通知并自动更新),其结构图如下:
public 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 notifyObervers(Newspaper newspaper) { foreach(var observer in observers) { observer.update(newspaper); } } } public class NewspaperOffice:Subject { //印刷报纸(触发通知) public void print() { Newspaper newspaper = new Newspaper(); notifyObervers(newspaper); } } public class Reader:Observer { //更新(阅读报纸) public void update(Newspaper newspaper ){} } public class Client { public static void Main(string[] args) { Reader reader = new Reader(); NewspaperOffice office = new NewspaperOffice(); office.attach(reader); office.print(); } }
其实利用.Net的委托可以更好的实现观察者模式,而且用委托的话,所有观察者的方法名不需要都是update,如下代码:
public class Subject { Action<Newspaper> registerMethod; //添加订阅方法 public void attach(Action<Newspaper> method) { registerMethod+=method; } //移出订阅方法 public void detach(Action<Newspaper> method) { registerMethod-=method; } //执行订阅方法 public void notifyObervers(Newspaper newspaper) { registerMethod(newspaper); } } public class NewspaperOffice:Subject { //印刷报纸(触发通知) public void print() { Newspaper newspaper = new Newspaper(); notifyObervers(newspaper); } } public class Reader:Observer { //更新(阅读报纸) public void IamReadNewspaper(Newspaper newspaper ){} } public class Client { public static void Main(string[] args) { Reader reader = new Reader(); NewspaperOffice office = new NewspaperOffice(); office.attach(Reader.IamReadNewspaper); office.print(); } }
但不用委托的用法也是有用的,比如,添加、移出订阅者、通知订阅者的操作是数据库的操作(把订阅者的信息存储在数据库里)
观察者模式的本质:触发联动。