zoukankan      html  css  js  c++  java
  • 观察者模式深入实践

    对于各位看官来说观察者模式都应该不陌生,我也看过一些介绍该模式的文章,但觉得例子中场景都设置的过于简单,未免有些千篇一律。所以,为了更深刻的理解观察者这

    个设计模式也就有了下面的这些代码。例子场景的设置是热水壶烧水,水温每次变化时通知注册的观察者,并输出相关水温变化的信息。由调用端触发热水壶的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();
            }
        }
    }

    最终效果图

  • 相关阅读:
    servlet 传值和取值问题
    .net 获取存储过程返回值和Output输出参数值
    游标使用
    java中直接根据Date获取明天的日期
    Linux通配符与特殊符号知识大全
    zabbix监控
    KVM介绍 虚拟化简史
    GFS文件系统
    Oracle JOB定时器
    IDEA JSP 不能使用EL表达式
  • 原文地址:https://www.cnblogs.com/huangzelin/p/5347699.html
Copyright © 2011-2022 走看看