观察者模式
观察者模式又叫发布-订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
下面举例天气预报通知,演示观察者模式:
首先定义观察者
/// <summary> /// 订阅者接口 /// </summary> public interface IObserver { //由被观察对象调用的更新方法,拉模式 void Update(ISubject subject); //由被观察对象调用的更新方法,推模式 void Update(string subjectState); } /// <summary> /// 天气观察者 /// </summary> public class WeatherObserver:IObserver { //观察者姓名 public string ObserverName { get; set; } #region TObserver 成员 //得到通知后所作的事情 public void Update(ISubject subject) { Console.WriteLine("{0} get weather message:{1}", ObserverName, subject.SubjectState); } public void Update(string subjectState) { Console.WriteLine("{0} get weather message:{1}", ObserverName, subjectState); } #endregion }
下面定义观察目标对象
/// <summary> /// 观察目标接口 /// </summary> public interface ISubject { //会改变的内容 string SubjectState { get; set; } //添加观察者 void Attach(IObserver observer); //删除观察者 void Detach(IObserver observer); //拉模式的通知方法定义 void Notify(ISubject subject); //推模式的通知方法定义 void Notify(string subjectState); } /// <summary> ///提供天气信息的观察目标 /// </summary> public class WeatherSubject:ISubject { #region TSubject 成员 //会改变的内容 private string weather; //观察者列表 private List<IObserver> weatherObservers = new List<IObserver>(); public string SubjectState { get { return weather; } set { weather = value; //在观察目标变化时通知所有观察者,推模式和拉模式二选一 this.Notify(this); //this.Notify(weather); } } public void Attach(IObserver observer) { if (!weatherObservers.Contains(observer)) { weatherObservers.Add(observer); } } public void Detach(IObserver observer) { if (weatherObservers.Contains(observer)) { weatherObservers.Remove(observer); } }
//遍历观察者列表,调用每一个观察者的update方法 public void Notify(ISubject subject) { foreach (IObserver observer in weatherObservers) { observer.Update(subject); } } public void Notify(string subjectState) { foreach (IObserver observer in weatherObservers) { observer.Update(subjectState); } } #endregion }
客户端完成观察者和目标的实例化和绑定
//定义被观察者 ISubject weather = new WeatherSubject(); //定义观察者 WeatherObserver observer1 = new WeatherObserver(); observer1.ObserverName = "Kelly"; WeatherObserver observer2 = new WeatherObserver(); observer2.ObserverName = "Mike"; //进行订阅 weather.Attach(observer1); weather.Attach(observer2); //更新被观察者状态 weather.SubjectState = "晴天"; //更新被观察者状态 weather.SubjectState = "雨天";
执行结果:
Kelly get weather message:晴天
Mike get weather message:晴天
Kelly get weather message:雨天
Mike get weather message:雨天
将一个系统分割成一系列相互协作的类有一个很不好的副作用,就是需要维护相关对象之间的一致性,我们不希望为了维护一致性而使各类紧密耦合,这样回给维护、扩展和重用带来不便。观察者模式所做的工作就是解耦合,让耦合双方都依赖于抽象,而不依赖与具体,使得各自的变化都不会影响另一边的变化。
当一个对象的改变需要同时改变其他对象,而又不知道具体有多少对象有待改变时,就应该考虑使用观察者模式。