设计模式-观察者模式

   1:观察者模式无疑是观察。举一个例子来说明一下观察者模式。比喻现在要开联合国(主题)大会,那么现在各国国家派出代表去参加(此时各国代表就是观察者)。代表把联合国商讨的结果带回来传递给国内人民,这个过程就是观察者模式。看下图

下面开始编码:

第一步:我们先看被观察者(就是主题),被观察者有什么特性呢,首先有观察者就是add,同时呢这个观察者不想观察了那就撤销delete,还有呢就是观察者观察到好的东西要通知告诉上层领导

那么这个接口我们就可以定义了

复制代码
/// <summary>
    /// 主题接口
    /// </summary>
    public interface ISubject
    {
        /// <summary>
        /// 注册参加的代表
        /// </summary>
        /// <param name="observer">代表</param>
        void Add(string Name,IObserver observer);
        /// <summary>
        /// 删除参加的代表
        /// </summary>
        /// <param name="observer"></param>
        void Delete(string Name, IObserver observer);
        /// <summary>
        /// 通知各国的代表
        /// </summary>
        void Notify();
    }
复制代码

第二步:我们该定义观察者了。观察者要干嘛呢,就是观察(其实就是监听,像不像奸细)得到信息了赶紧就去汇报,所以接口就比较好定义了就是传递信息(当然实际项目中就是得到信号以后你自己的操作)

复制代码
/// <summary>
    /// 观察者(这里指的是各国派的代表)
    /// </summary>
    public interface IObserver
    {
        /// <summary>
        /// 代表通过本国民众
        /// </summary>
        void UpdateHoliday(string Message);
    }
复制代码

第三步:实现被观察者

复制代码
/// <summary>
    /// 实现主题
    /// </summary>
    public class Subject : ISubject {

        private Dictionary<string, IObserver> allObservers = new Dictionary<string, IObserver>(5);
        /// <summary>
        /// 通过信息
        /// </summary>
        public string PublishInfo { get; set; }

        /// <summary>
        /// 注册代表
        /// </summary>
        /// <param name="Name">代表名称</param>
        /// <param name="observer"></param>
        public void Add(string Name, IObserver observer) {
            if (allObservers.ContainsKey(Name)) {
                allObservers[Name] = observer;
            }
            else {
                allObservers.Add(Name, observer);
            }
        }
        /// <summary>
        /// 删除代表
        /// </summary>
        /// <param name="Name">代表名称</param>
        /// <param name="observer"></param>
        public void Delete(string Name, IObserver observer) {
            if (allObservers.ContainsKey(Name)) {
                allObservers.Remove(Name);
            }
        }
        /// <summary>
        /// 通知各国代表
        /// </summary>
        public void Notify() {
            foreach (var observer in allObservers) {
                observer.Value.UpdateHoliday(PublishInfo);
            }
        }
复制代码

这里面的逻辑自己可以根据项目需要来定义

第四步:实现观察者

复制代码
/// <summary>
    /// 日本
    /// </summary>
    public class JapanObserver : IObserver
    {
        /// <summary>
        /// 把假日更新
        /// </summary>
        /// <param name="Message"></param>
        public void UpdateHoliday(string Message)
        {
            Console.WriteLine("我是日本代表 通过广告转告民众:{0}", Message);
        }
    }

    /// <summary>
    /// 美国
    /// </summary>
    public class AmericaObserver : IObserver {
        public void UpdateHoliday(string Message) {
            Console.WriteLine("我是美国代表 通过广播转告民众:{0}", Message);
        }
    }

/// <summary>
    /// 中国
    /// </summary>
    public class ChinaObserver : IObserver {
        public void UpdateHoliday(string Message) {
            Console.WriteLine("我是中国代表 通过电视转告民众:{0}", Message);
        }
    }

/// <summary>
    /// 英国
    /// </summary>
    public class BritishObserver : IObserver {
        public void UpdateHoliday(string Message) {
            Console.WriteLine("我是英国代表 通过报纸转告民众:{0}", Message);
        }
    }

/// <summary>
    /// 德国
    /// </summary>
    public class GermanyObserver : IObserver {
        public void UpdateHoliday(string Message) {
            Console.WriteLine("我是德国代表 通过媒体转告民众:{0}", Message);
        }
    }
复制代码

这里有5个不同的观察者,因为他们来自不同的国家(项目中可以根据实际情况)

第五步:运行看下结果

 总结:观察者模式定义了对象之间的一种联系,使得当一个对象改变状态时,所有其他对象可以相应的被通知到。通常,系统有一个新状态发布者,以及许多想要得到状态通知的订阅者。

2:我们发现这个和事件委托很像,也是定义一个委托,然后在定义一个事件,当状态发生改变的时候触发事件。下面看看编码

A:主题

复制代码
/// <summary>
    /// 委托/事件实现主题
    /// </summary>
    public class SubjectEventHandler
    {
        //定义一个发送信息的委托
        public delegate void SendMessage(string str);
        //定义一个事件
        public event SendMessage SendTest;        
        /// <summary>
        /// 公布信息
        /// </summary>
        public string PublishInfo { get; set; }
        /// <summary>
        /// 发送信息
        /// </summary>
        public void Notify()
        {            
            if (SendTest!=null)
            {
                SendTest(PublishInfo);
            }
        }
    }
复制代码

 B:得到信息后的操作

复制代码
/// <summary>
    /// 响应事件后的操作
    /// </summary>
    public class ObserverEventHandler {
        public void Display(string str)
        {
            Console.WriteLine(str);
        }
    }
复制代码

C:触发事件

SubjectEventHandler subjectEvent = new SubjectEventHandler();
            subjectEvent.PublishInfo = "实施2.5天假期制";
            ObserverEventHandler observerEvent = new ObserverEventHandler();            
            subjectEvent.SendTest += new SubjectEventHandler.SendMessage(observerEvent.Display);
            subjectEvent.Notify();

D:显示结果

 

3:在前面我们说过action也是用过表示委托的下面我们来看看action的操作

A:定义主题

复制代码
/// <summary>
    /// 委托/事件实现主题
    /// </summary>
    public class SubjectEventHandler
    {
        public Action<string> SendAction; 
        /// <summary>
        /// 公布信息
        /// </summary>
        public string PublishInfo { get; set; }
        /// <summary>
        /// 发送信息
        /// </summary>
        public void Notify() {
            if (SendAction != null) {
                SendAction(PublishInfo);
            }
        }
复制代码

B:

复制代码
/// <summary>
    /// 响应事件后的操作
    /// </summary>
    public class ObserverEventHandler {
        public void Display(string str)
        {
            Console.WriteLine(str);
        }
    }
复制代码

C:响应

    SubjectEventHandler subjectEvent = new SubjectEventHandler();
            subjectEvent.PublishInfo = "实施2.5天假期制";
            ObserverEventHandler observerEvent = new ObserverEventHandler();
            Action<string> action = observerEvent.Display;
            subjectEvent.SendAction = action;    
            subjectEvent.Notify();

同样实现了2中的效果

总结:个人觉得如果项目较大,而且偏向于有用户管理信息,用观察者模式。如果是比较小的项目或者只是触发一下事件就可以搞定可以使用事件委托。比喻我们要获取数据库某一个表中更新的数量,我们就不必每一次就去读取数据库,而是缓存中读取,但是缺点就是没有达到及时性,那么现在我们就可以用委托,每次更新一条数据那么就触发一次事件去数据库读取来更新缓存即可

posted @   朝向远方  阅读(2181)  评论(2编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示