• C#基础笔记——委托(Delegate)和事件(Event)


    一、概述

    委托首先是一个方法指针。

    委托也是一个类,当对其进行实例化的时候,要将引用方法作为它的构造方法的参数。

    事件是为委托施加保护的,它封装了委托类型的变量,使得在类的内部,不管你声明它是public还是protected,它总是private的。在类的外部,注册“+=”和注销“-=”的访问限定符与你在声明事件时使用的访问符相同。

    二、委托和事件的使用及Observer设计模式:

    Observer设计模式:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。

    我们用Observer设计模式实现高档的热水器烧水过程,给它通上电,当水温超过95度的时候:

      1、扬声器会开始发出语音,告诉你水的温度;

      2、液晶屏也会改变水温的显示,来提示水已经快烧开了,同时显示热水器厂家名称。

    现在我们需要写个程序来模拟这个烧水的过程,我们将定义一个类来代表热水器,我们管它叫:WaterHeater,它有代表水温的字段,叫做temperature;当然,还有必不可少的给水加热方法heatUp()。一个发出语音警报的类Alarm和一个显示类Screen,他们继承Observer抽象类。

    首先我们需要一个热水器类:

        public delegate void ActionEventHandler(object sender, ConcernEventArgs e);
    
        public class WaterHeater
        {
            public event ActionEventHandler action;
    
            private string manufacturer ;
    
            public string Manufacturer
            {
                get { return manufacturer; }
                private set { manufacturer = value; }
            }
    
            public WaterHeater(string manufacturer)
            {
                this.manufacturer = manufacturer;
            }
    
            public void attach(Observer observer)
            {
                action += observer.display;
            }
            public void detach(Observer observer)
            {
                action -= observer.display;
            }
    
            public static WaterHeater getInstance(string manufacturer)
            {
                return new WaterHeater(manufacturer);
            }
    
            public void heatUp()
            {
                for (int i = 0; i <= 100; i++)
                {
                    if (i > 95)
                    {
                        ConcernEventArgs e = new ConcernEventArgs(i,this.manufacturer);
    
                        action.DynamicInvoke(this, e);
    
                    }
                }
            }
        }

    然后是一个标准的事件模型:

    事件模型规范:

    1. 委托类型名称以EventHandler结束;

    2. 原型返回值为void;

    3. 事件原型具有两个参数:sender表示事件触发者,e表示事件参数;

    4. 事件参数名称要以EventArgs结束;

        public class ConcernEventArgs : EventArgs
        {
            internal readonly int temprature;
            internal readonly string manufactor;
    
            public ConcernEventArgs(int temprature, string manufactor)
            {
                this.temprature = temprature;
                this.manufactor = manufactor;
            }
        }

    此时我的热水器类就完成了。

    我们还需要一个观察者Observer抽象类

    public abstract class Observer
        {
            public abstract void display(object sender, ConcernEventArgs e);
        }

    实现Alarm类继承Observer抽象类重写display方法:

        public class Alarm:Observer
        {
            public static Alarm getInstance()
            {
                return new Alarm();
            }
    
            public override void display(object sender, ConcernEventArgs e)
            {
                Console.WriteLine("Alarm:" + e.manufactor);
                Console.WriteLine("Alarm:"+e.temprature );
            }
        }

    实现Screen类继承Observer抽象类重写display方法:

        public class Screen : Observer
        {
            public static Screen getInstance()
            {
                return new Screen();
            }
    
            public override void display(object sender, ConcernEventArgs e)
            {
                Console.WriteLine("Screen:" + e.manufactor);
                Console.WriteLine("Screen:" + e.temprature);
            }
        }

    下面我们用控制台程序实现热水器烧水过程:

        class Program
        {
            static void Main(string[] args)
            {
                Alarm alarm = Alarm.getInstance();
                Screen screen = Screen.getInstance();
                WaterHeater waterHeater = WaterHeater.getInstance("BOB");
                waterHeater.attach(alarm);
                waterHeater.attach(screen);
                waterHeater.heatUp();
                Console.ReadKey();
            }
        }

    Observer设计模式中主要包括如下两类对象:

    Subject:主题对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个监视对象,它包含的其他对象所感兴趣的内容,就是temprature字段,当这个字段的值快到100时,会不断把数据发给监视它的对象。

    Observer:监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器和显示器,它们采取的行动分别是发出警报和显示水温。

    在本例中,事情发生的顺序应该是这样的:

    1.警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。

    2.热水器知道后保留对警报器和显示器的引用。

    3.热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的display()方法、显示器的display()方法。

  • 相关阅读:
    mysql sum 重复计算_mysql join sum时数据重复问题及解决方案
    mysql数据库中,查询一个表的下一条数据减上一条数据的值的写法
    FROM_UNIXTIME 格式化MYSQL时间戳函数
    Mysql 中日期类型bigint和datetime互转
    mysql 按照指定字段的指定数据进行排序 filed函数
    MYSQL使用group by,如何查询出总记录数
    iptables添加开放端口
    MySQL之You can't specify target table for update in FROM clause解决办法
    epoll 使用 LT + 非阻塞 IO 和 ET + 非阻塞 IO 比较
    sizeof和strlen的比较
  • 原文地址:https://www.cnblogs.com/Abel-Zhang/p/DelegateAndEvent.html
Copyright © 2020-2023  润新知