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()方法。

 

posted @ 2013-11-03 09:25  Abel.Zhang  阅读(504)  评论(0编辑  收藏  举报