观察者模式深入实践
对于各位看官来说观察者模式都应该不陌生,我也看过一些介绍该模式的文章,但觉得例子中场景都设置的过于简单,未免有些千篇一律。所以,为了更深刻的理解观察者这
个设计模式也就有了下面的这些代码。例子场景的设置是热水壶烧水,水温每次变化时通知注册的观察者,并输出相关水温变化的信息。由调用端触发热水壶的Run()方法来开
启整个烧水和水温变化通知流程。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { //本例子实现的是热水壶烧水,水温变化时通知订阅者,订阅者输出水温变化信息 #region 主题、观察者、热水壶接口定义 public interface ISubject { string SubjectName { get; } void Attach(IObserver observer); void Detach(IObserver observer); void Notify(); } public interface IObserver { void Update(); } public interface IHotWaterPot : ISubject { /// <summary> /// 当前温度 /// </summary> float CurrentTemp { get; } /// <summary> /// 温度变化 /// </summary> void TempChanged(); /// <summary> /// 开始烧水 /// </summary> void Run(); } #endregion #region 主题与观察者抽象类定义,目的是代码重用 public abstract class Observer : IObserver { private ISubject _subject = null; public Observer(ISubject subject) { this._subject = subject; } public ISubject Subject { get { return this._subject; } } public abstract void Update(); } public abstract class Subject : ISubject { private string _subjectName = string.Empty; private IList<IObserver> _observers = new List<IObserver>(); public Subject(string subjectName) { this._subjectName = subjectName; } public void Attach(IObserver observer) { this._observers.Add(observer); } public void Detach(IObserver observer) { if (this._observers.Contains(observer)) { this._observers.Remove(observer); } } public string SubjectName { get { return this._subjectName; } } public virtual void Notify() { foreach (IObserver item in this._observers) { item.Update(); } } } #endregion #region 热水壶类定义,实现IHotWaterPot接口,具备了烧水的能力,同时本身也是一个Subject public class HotWaterPot : Subject, IHotWaterPot { private string _potName = string.Empty; private float _currentTemp = 0f; public HotWaterPot(string potName,float waterTemp) : base("热水壶烧水主题") { this._potName = potName; this._currentTemp = waterTemp; } public float CurrentTemp { get { return this._currentTemp; } } public void TempChanged() { base.Notify(); } public void Run() { while(this._currentTemp < 100f) { this._currentTemp += 1; this.TempChanged(); Thread.Sleep(1000); } Console.WriteLine("水烧开了。。。。"); } } #endregion #region 热水壶观察者类定义 public class WaterPotObserver : Observer { private string _name = string.Empty; private IHotWaterPot _waterPort = null; public WaterPotObserver(ISubject subject, string name) : base(subject) { this._name = name; } public override void Update() { this._waterPort = this.Subject as IHotWaterPot; if (this._waterPort != null) { Console.WriteLine("Time:{0},观察者:{1},收到主题名为:{2}的消息通知,当前温度是:{3}。。。。" ,DateTime.Now, this._name, this.Subject.SubjectName,this._waterPort.CurrentTemp); } } } #endregion class Program { static void Main(string[] args) { #region 定义subject和observer实例,并进行关联与注册 ISubject subject = new HotWaterPot("美的点热水壶", 80); IObserver observer1 = new WaterPotObserver(subject, "张三"); IObserver observer2 = new WaterPotObserver(subject, "李四"); subject.Attach(observer1); subject.Attach(observer2); #endregion //将subject转换为IHotWaterPot类型,并调用Run()方法触发烧水动作 IHotWaterPot pot = (IHotWaterPot)subject; pot.Run(); Console.ReadKey(); } } }
最终效果图