• 在实际项目中使用观察者模式 前篇——委托和事件


    我们公司面试初级C#的笔试题有一道题目:“请用代码实现:狗叫,主人被惊醒,猫跑了”。

    这是一道很典型的可以使用观察者模式来解答的题目,可惜来做题的伙伴经常没有答上,今天我就从这道小题目开始,由浅到深讲讲观察者模式。

    但是在讲观察者模式之前我们先要了解委托和事件。

    委托和事件

    委托(delegate)本质上是函数指针(在js里是函数变量的引用,js里并不需要声明delegate)。通俗来理解就是把一件事交给别人去做。

    在代码里,“事情”就是functioin或method。delegate的作用就是把functioin或method装起来,不在new的地方执行,而在别的地方执行。

    delegate需要把要执行的method注册进去,即告诉被委托人你要委托给他的事。

    知道了委托,我们可以先试试水,用它来实现最开始说的笔试题的第一版。这里大家先不用去想为什么要这样做。

    首先定义三位演员和他们要做的事:

        public class Dog
        {
            public void Bark()
            {
                Console.WriteLine("狗:汪汪汪");
            }
        }
    
        public class Master
        {
            public void WakeUp()
            {
                Console.WriteLine("主人:醒来");
            }
        }
    
        public class Cat
        {
            public void Run()
            {
                Console.WriteLine("猫:跑了");
            }
        }

    其次,我们把三位演员new出来,并把他们要做的事放入委托,最后通过“中介人”来执行委托:

            public delegate void TheTestDelegate();
            //定义一个中间人来执行委托,需要接收一个委托参数
            private static void Agent(TheTestDelegate doSomething) {
                doSomething();
            }
    
            static void Main(string[] args)
            {
                Dog dog = new Dog();
                Master master = new Master();
                Cat cat = new Cat();
                TheTestDelegate testDelegate;
                //注册要委托的事
                testDelegate = dog.Bark;
                testDelegate += master.WakeUp;
                testDelegate += cat.Run;
                //执行委托
                Agent(testDelegate);
            }

    这样一来,中间人就把我们刚刚委托给他的事都给办了

    这样写的好处是显而易见的。委托将Main和各位演员的操作隔离了。每次执行委托时,我并不需要知道各位演员即将要做什么骚操作(比如狗突然喵喵叫)。从而达到了解耦的效果。

    知道了什么是委托和委托怎么用之后,接下来我们看看什么是事件:

    事件(event)是一种封装了的委托,他做了什么封装,为什么要这么封装呢?我们来继续研究上面的例子。

    在上面的代码里,委托被定义成了公共的变量。这样就意味着谁都可以修改,那显然不行。

    所以我们要让中介人自己管理他的委托合同。只有雇佣(new)他的人,才可以委托他干活。而作为发布人的我们仅需要发布委托和触发执行事件。

    首先我们把Agent单独建一个class,但是我们要怎么让中介人自己管理委托呢?即使把delegate移到Agent里,如果将delegate声明为public,那照样谁都可以赋值。若声明为private,则谁都委托不了。

    这时我们可以试试看用事件:

        //定义委托
        public delegate void TheTestDelegate();
    
        public class Agent
        {
            //声明事件
            public event TheTestDelegate theEvent;
    
            public void DoDelegate()
            {
                theEvent();
            }
        }
    
            static void Main(string[] args)
            {
                Agent agent = new Agent();
                //注册要委托的事
                agent.theEvent += new Dog().Bark;//注意,这里第一次不需要也不能用=号了
                agent.theEvent += new Master().WakeUp;
                agent.theEvent += new Cat().Run;
                //触发事件
                agent.DoDelegate();
            }

    大家可能觉得有疑问:这不还是用了public吗?

    其实不然,为什么这里把method注册进事件不需要也不能使用“=”号了呢?

    其实声明事件类似于把委托声明成了属性 (Property)。我们的+=和-=相当于访问了set访问器,而真正的delegate其实被声明成了private。

    好了,搞了这么久,前戏终于做完了。接下来可以开始说说观察者模式了。

  • 相关阅读:
    re正则表达式公式讲解3
    re正则表达式2
    re正则表达式公式讲解1
    洛谷 P2962 [USACO09NOV]灯Lights
    9.26模拟赛
    BZOJ 1567: [JSOI2008]Blue Mary的战役地图

    洛谷 P2919 [USACO08NOV]守护农场Guarding the Farm
    洛谷P3252 [JLOI2012]树
    P3183 [HAOI2016]食物链
  • 原文地址:https://www.cnblogs.com/lws66/p/11218738.html
Copyright © 2020-2023  润新知