• 观察者模式用途总结


    啥是观察者模式

    定义了对象间一对多依赖,当对象状态发生改变时,所有依赖项都会接收信息并更新。

    设计模式一般是不分语言的。因为现在主要使用c#,就按照这个来总结下。
    参与过不少项目,发现多数项目中观察者模式使用非常频繁,主要是信息推送,像通信时接收发送时推送给谁,设备状态改变时推送给谁。
    仔细琢磨着就像是关注好友,当好友发朋友圈,所有关注他/它/她/TA的人都会收到信息推送。

    想一想,一个对象,多个。。。依赖,肯定都有一个共同点,都想。。。做点啥,所以现有一个接口。

    public interface Observer
     {
             void update(DATA_MESSAGE date);
     }
    
    • 1
    • 2
    • 3
    • 4

    其中DATA_MESSAGE date 自定义一个信息类,因为单纯的只想说点啥。想做别的事就自己改变下接口参数。

    这时候也许又有区分了,有些是行动派,做的方式不一样,有些就不做,统一 一下就再来一个接口

    public interface DisplayElement
        {
             void display(DATA
             _MESSAGE date);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    所有。嗯。。依赖项可以去继承这个接口 项设备信息展示,信息推送,再或者,买包包送女神啥的。。。你随意。

    有请大怨种一号(订阅者/观察者)

    关注TA。。。发现TA。。。 去做啥。。。拉黑TA(移除)

    public class obTest : Observer, DisplayElement
     {
     	public obTest() //注册
            {
                RegistElement.registerMethod((int)Flag.observer0, this);
            }
             public void update(DATA_MESSAGE date) //信息变更
            {
                Console.WriteLine("No0.大怨种,say hello");
                display(date);
            }
              public void display(DATA_MESSAGE date) //执行方法
            {
                string str =  string.Format("时间:{0} {1}", date.time, date.content);
                Console.WriteLine(str);
                //下边两行是朗读 随意
                SpVoiceClass voice = new SpVoiceClass();
                voice.Speak(str, SpeechVoiceSpeakFlags.SVSFlagsAsync);
            }
             public void goAway() 
            {
                RegistElement.removeRegister((int)Flag.observer0);
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    来个枚举定义下观察者类型

     public enum Flag 
        {
            observer0,//NO0大怨种
            observer1,//NO1大怨种
            observer2,//NO2大怨种
            observer3 //NO3大怨种
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    有了这些,就要说说被依赖者了。

    第一步

    首先TA要有一个集合\群组\字典。。。用来管理备胎。。管理订阅者。。依赖项等等

    public static Dictionary register = new Dictionary();
    
    • 1

    我用的是字典,当然根据需求来。int 是标志 0大怨种 1渣男 3王老五 4隔壁老王。。。

    第二步

    TA还要有一个让人家关注的方法 或者说是注册,申请好友等等。

    public static void registerMethod(int flag, Observer server)
            {
                Observer ob = null;
                
                if (!register.TryGetValue(flag, out ob))
                    register.Add(flag,server);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    再其次还要有一个让人家删除,移除依赖者的方法(呸,渣渣,互删吧)

     public static void removeRegister(int flag) 
            {
                Observer ob = null;
                if (register.TryGetValue(flag,out ob))
                    register.Remove(flag);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    第三步

    TA的状态信息改变了,推送给所有关注者\依赖项(或者根据需求推送给特定的依赖项方法逻辑非一成不变)

    	public static void stateChange(DATA_MESSAGE date) 
            {
                notifyListeners(date);
            }
            public static void notifyListeners(DATA_MESSAGE date) 
            {
               foreach( var obD in register)
                {
                    obD.Value.update(date);
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    好了测试一下

    	    obTest obt = new obTest();
                obTest2 ob2 = new obTest2();
                 DATA_MESSAGE msg = new DATA_MESSAGE((int)Flag.observer0, "说点啥??", DateTime.Now.ToShortDateString());
                RegistElement.stateChange(msg); //群发
                 obt.goAway();//移除了一个
                  msg = new DATA_MESSAGE((int)Flag.observer0, "有一个拉黑了,他还能收到吗??", DateTime.Now.ToShortDateString());
                RegistElement.stateChange( msg);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    结束。
    其实分组处理似乎更好一点,给注册中 某一类人\依赖项发送

     public static Dictionary> register = new Dictionary>();
    
    • 1

    有需要的可以研究下。简单。
    个人技术有限,用这种方式分享下,感觉自己理解更深一点了。真好。

  • 相关阅读:
    C++ 类型转换
    用 SQL 找出某只股票连续上涨的最长天数
    非常有用的一个正则表达式.匹配多个任意字符
    分布式.数据库架构
    QueryWrapper里执行mysql函数
    操作系统相关
    刚刚阿里面软件测试回来,3+1面任职阿里P7,年薪28*15薪
    第八章 贪心
    Go 基础语法 轻松上手 goland~
    面试复习题--算法汇总
  • 原文地址:https://blog.csdn.net/weixin_40899924/article/details/126946477