zoukankan      html  css  js  c++  java
  • 观察者模式的"最佳实践"

    记录一次观察者模式的使用,目前需求是这样的,我有很多个模块,模块与模块之间是相互独立的,当我某个地方触发到相应的逻辑或状态时,需要让其他所有模块都去做自己相应的逻辑处理,文章中有删减,大致是这么个实现思路。

    一、代码实现过程

    1、为方便其他地方直接调用,这里直接使用静态类,主要提供3个对外的方法,分别是注册监听、取消监听以及发布。

    image-20210817142823953

    2、创建一个订阅者类,

    private class Listener
            {
                /// <summary>
                /// 编号
                /// </summary>
                public int Id { get; set; }
    
                /// <summary>
                /// 事件处理钩子
                /// </summary>
                public EventHandler Handler { get; set; }
            }
    

    注意这里EventHandler是一个委托,方便我们后续直接执行操作方法,我们需要声明以下

    public delegate void EventHandler();
    

    3、再创建一个字典用于存储订阅者们,我这里是使用一个枚举作为Key,一个列表作为Value,实际视具体业务而定

    /// <summary>
            /// 事件映射
            /// </summary>
            private static Dictionary<EventEnum, List<Listener>> events = new Dictionary<EventEnum, List<Listener>>();
    

    4、编写注册监听的逻辑

    public static void Register(int id, EventEnum eventEnum, EventHandler handler)
            {
                if (!events.ContainsKey(eventEnum))
                {
                    List<Listener> listeners = new List<Listener>();
                    listeners.Add(new Listener() { Id = id, Handler = handler });
                    events.Add(eventEnum, listeners);
                }
                else
                {
                    List<Listener> listeners = events[eventEnum];
                    listeners.Add(new Listener() { Id = id, Handler = handler });
                }
            }
    

    首先检查字典中有无这个key,如果没有才注册(添加)进去,List列表中就是所有订阅者

    5、编写取消注册监听

    public static void Unregister(int id, EventEnum eventEnum, EventHandler handler)
            {
                if (events.ContainsKey(eventEnum))
                {
                    List<Listener> listeners = events[eventEnum];
                    for (int i = listeners.Count; i > 0; i--)
                    {
                        Listener listener = listeners[i - 1];
                        if (listener.Id.Equals(id) && listener.Handler.GetType() == handler.GetType())
                        {
                            listeners.Remove(listener);
                        }
                    }
                }
    
            }
    

    大致思路就是这样,如果要取消的键存在,我们则获取到字典中该枚举的所有的订阅者,然后去遍历,如果id和handler吻合,就从字典中移除掉

    6、最后再实现发布订阅,用于通知已注册监听的订阅者

    public static void Publish(int id, EventEnum eventEnum)
            {
                if (events.ContainsKey(eventEnum))
                {
                    List<Listener> listeners = events[eventEnum];
                    foreach (var item in listeners)
                    {
                        if (item.Id.Equals(id))
                        {
                            item.Handler();
                        }
                    }
                }
            }
    

    就是遍历,然后逐个执行刚才那个委托。

    7、最后就是使用了,为了简化,这里直接简单记录一下,后续根据实际业务情况去对应的地方注册和发布就完事了

    public class Program
        {
            static void Main(string[] args)
            {
                //订阅监听
                SubscriberManager.Register(1, EventEnum.Status1, HandlerMethod);
                SubscriberManager.Register(2, EventEnum.Status3, HandlerMethod2);
    
                //发布
                SubscriberManager.Publish(1, EventEnum.Status1);
                //SubscriberManager.Publish(2, EventEnum.Status3);
    
                Console.ReadKey();
            }
    
            //监听到发布事件后所要执行的处理方法
            private static void HandlerMethod2()
            {
                Console.WriteLine("执行方法2");
            }
    
            private static void HandlerMethod()
            {
                Console.WriteLine("执行方法1");
            }
        }
    

    总结一下:观察者模式很适合当一个状态发生改变时,需要通知到多处的使用场景,实现起来也比较简单易理解。

    对应的代码再Github仓库:https://github.com/luchong0813/DesignModel/tree/main/11-Listener

  • 相关阅读:
    PMP--4.3-1 进度管理计划
    PMP--4.3 规划进度管理&规划进度管理工具与技术--进度管理计划
    PMP--4.2 规划范围管理--范围管理计划--需求管理计划
    PMP工具与技术篇--4.2.3 WBS分解
    PMP--4.2.3-1 范围基准**--WBS词典
    PMP --4.2.3 创建WBS(工作分解结构)--WBS--范围基准
    PMP工具与技术篇--4.2.2 定义范围工具与技术总结--产品分析
    PMP--4.2.2 定义范围--项目范围说明书
    PMP工具与技术篇--4.2.1-6 原型(DEMO)法
    PMP工具与技术篇--4.2.1-5 观察与交谈(人际关系与团队技能)
  • 原文地址:https://www.cnblogs.com/chonglu/p/15152269.html
Copyright © 2011-2022 走看看