• C#-设计模式-观察者模式


    1.定义

    观察者模式说白了就是事件;之前没有观察者模式的时候,当我们需要考察属性的状态然后作出相应的处理,我们只能当状态满足的时候去调用方法。

    不过这样就造成了事件处理和事件绑定在了一起,一旦我们要添加其他的处理功能,就不得不修改原有的检测代码,对于修改并不友好。

    2.观察者模式的发展

    2.1 一个简单的需求

    对于一个简单的流程比如说,检测谁有没有烧开,以前没有事件的时候,如果我们就需要写如下代码;

    public class BoilWater
    {
        public int waterTemperature = 0;
    
        public void Boil()
        {
            for (int i = 0; i < 100; i++)
            {
                waterTemperature = i;
                Thread.Sleep(100);
                if (waterTemperature == 100)
                {
                    Call();
                }
            }
        }
    
        public void Call()
        {
            Console.Write("The Water is Boiled!");
        }
    }

    如上就是检测看,谁有没有烧开,如果水烧开了(到达100C),就调用通知方法(Call);

    但是上面的代码缺点也很明显,那就是:一旦我们要增加水烧开后的处理程序,我们就不得不修改Boil方法;

    那有没有办法可以让我们不修改代码的情况下,在运行中动态的去修改水烧开时的处理程序呢?答案是肯定的,那就是使用观察者模式;

    2.2 观察者模式

    public class BoilWater
    {
        public int waterTemperature = 0;
    
        public IList<RunInter> Observers = new List<RunInter>();
    
        public void Boil()
        {
            for (int i = 0; i < 100; i++)
            {
                waterTemperature = i;
                Thread.Sleep(100);
                if (waterTemperature == 100)
                {
                    CallAllObserve();
                }
            }
        }
    
        public void CallAllObserve()
        {
            foreach (var item in Observers)
            {
                item.Run();
            }
        }
    
        public void AddObserver(RunInter runner)
        {
            Observers.Add(runner);
        }
    
        public void RemoveObserver(RunInter runner)
        {
            Observers.Remove(runner);
        }
    }
    
        public interface RunInter
        {
            void Run();
        }
    
        public class Call : RunInter
        {
            public void Run()
            {
                Console.Write("The Water is Boiled!");
            }
        }
    
        public class DoOtherThing : RunInter
        {
            public void Run()
            {
                Console.Write("Do Other Things");
            }
        }

    这里我们在被观察的类中放一个存储接口的列表,然后在事件满足的时候,将列表中的每一个接口都执行一遍,而且因为有AddObserver和RemoveObserver方法,因此在程序运行的过程中我们也可以动态的添加新的处理代码,或删除已有的处理代码。

    但是这样做确实是有一点繁琐,要定义接口,还要再检测类中加上对应的列表,还好.NET已经为我们设计了完美的替代方案,那就是使用委托和事件;

    2.3 使用委托和事件来实现观察者模式

    public class BoilWater
    {
        public int waterTemperature = 0;
    
        private event Action actions;
    
        public void Boil()
        {
            for (int i = 0; i < 100; i++)
            {
                waterTemperature = i;
                Thread.Sleep(100);
                if (waterTemperature == 100)
                {
                    actions();
                }
            }
        }
    
        public void AddObserver(Action runner)
        {
            actions += runner;
        }
    
        public void RemoveObserver(Action runner)
        {
            actions -= runner;
        }
    }

    调用的时候只需要:

    var boilWater = new BoilWater();
    boilWater.AddObserver(() =>
    {
        Console.WriteLine("Water is Boiled");
    });
    boilWater.AddObserver(() =>
    {
        Console.WriteLine("Do Other Things");
    });

    这样当水开的时候,两个控制台打印的方法,都会被执行了。

    其实在这里的Action就是.Net自带的委托对象,其实委托我们在和上面的代码对比后,就可以认为他是一系列相似方法的集合列表,当执行委托之后,这个集合中的每一个方法就会依次被执行(有先后顺序,并不是并发执行);

    但这种方式就为我们实现观察者模式的逻辑提供的很大的方便。

    2.4 委托和事件的区别

    2.3中的代码我使用了event关键字,就是讲委托声明为事件了,很多人区分不出委托和事件的区别,其实很简单,事件是一种特殊的委托;

    既然是委托,其实说到底他还是方法的集合,当执行事件后,这个集合中的所有方法都会被执行;

    区别在于,委托可以在委托所属的类外面进行添加和删除操作;但是事件不行,事件只能在事件所属的类内部进行添加和删除操作。

    3.特点

    优点:将事件的发生和事件的处理分离开,并且可以动态的添加和删除处理方法

    缺点:处理方法中如果有互相引用的情况,就会引起系统崩溃,而且解耦的手法影响了代码的执行效率(所有的设计模式几乎都有该缺点)

    希望各位学习愉快;

  • 相关阅读:
    PIE SDK介绍
    PIE软件介绍
    PIE SDK与Python结合说明文档
    转载博客(Django2.0集成xadmin管理后台遇到的错误)
    python+django学习二
    python+django学习一
    HTML练习二--动态加载轮播图片
    HTML练习一
    LeetCode 999. 车的可用捕获量
    LeetCode 892. 三维形体的表面积
  • 原文地址:https://www.cnblogs.com/gamov/p/10523310.html
Copyright © 2020-2023  润新知