ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Delegates 学习简记三

Delegates 学习简记三

原创 Linux操作系统 作者:kirinri 时间:2009-03-25 18:12:07 0 删除 编辑
Normal 0 false false false MicrosoftInternetExplorer4 Delegates 学习简记三

 

委托、事件与Observer设计模式

 

简记了两篇关于delegate 的内容,接着再来。

Observer设计模式中实际上只包含了两类对象,一个是Subject(主题),一个是Observer(观察者)。它们之间的角色是:

 

Subject:主题(被监视对象),它往往包含着Observer所感兴趣的内容。

Observer:观察者,它观察Subject。当Subject中的某件事发生的时候(通常是它所感兴趣的内容改变的时候),会被自动告知,而Observer则会采取相应的行动(通常为更新自身状态或者显示输出)

 

学习一个例子:有一个热水器,通电后水温超过95度时

  1. 发出语音提示水的温度
  2. 液晶屏显示水温

 

热水器 Heater

水温 temperature

加热方法 BoilWater()

 

语音提示 MakeAlert()

显示水温 ShowMsg()

 

程序:Heater

 

using System;

using System.Collections.Generic;

using System.Text;

 

namespace Observer

{

    class Heater

    {

        // 水温

        private int temperature;

 

        public void BoilWater()

        {

            for (int i = 0; i <= 100; i++)

            {

                temperature = i;

                if (temperature >= 95)

                {

                    MakeAlert(temperature);

                    ShowMsg(temperature);

                }

            }

        }

 

        // 语音提示

        private void MakeAlert(int paraTemper)

        {

            Console.WriteLine("Alert: 现在水的温度是{0}", paraTemper);

        }

 

        // 显示水水温

        private void ShowMsg(int paraTemper)

        {

            Console.WriteLine("Display: 现在水的温度是{0}", paraTemper);

        }

 

        static void Main(string[] args)

        {

            Heater ht = new Heater();

            ht.BoilWater();

        }

    }

}

 

Alert: 现在水的温度是95

Display: 现在水的温度是95

Alert: 现在水的温度是96

Display: 现在水的温度是96

Alert: 现在水的温度是97

Display: 现在水的温度是97

Alert: 现在水的温度是98

Display: 现在水的温度是98

Alert: 现在水的温度是99

Display: 现在水的温度是99

Alert: 现在水的温度是100

Display: 现在水的温度是100

Press any key to continue . . .

 

Observer设计模式:

面向对象设计,高内聚低耦合,如果现有Heater分成三部分,Heater Alarm Display

各自负责各自的功能。如下:

using System;

using System.Collections.Generic;

using System.Text;

 

namespace Observer

{

    class Heater

    {

        // 水温

        private int temperature;

 

        public void BoilWater()

        {

            for (int i = 0; i <= 100; i++)

            {

                temperature = i;

                if (temperature >= 95)

                {

                    //MakeAlert(temperature);

                    //ShowMsg(temperature);

                }

            }

        }

 

 

        //// 语音提示

        //private void MakeAlert(int paraTemper)

        //{

        //    Console.WriteLine("Alert: 现在水的温度是{0}", paraTemper);

        //}

 

        //// 显示水水温

        //private void ShowMsg(int paraTemper)

        //{

        //    Console.WriteLine("Display: 现在水的温度是{0}", paraTemper);

        //}

 

        static void Main(string[] args)

        {

            Heater ht = new Heater();

            ht.BoilWater();

        }

    }

 

    class Alarm

    {

        // 语音提示

        private void MakeAlert(int paraTemper)

        {

            Console.WriteLine("Alert: 现在水的温度是{0}", paraTemper);

        }

    }

 

    class Display

    {

        // 显示水水温

        private void ShowMsg(int paraTemper)

        {

            Console.WriteLine("Display: 现在水的温度是{0}", paraTemper);

        }

    }

}

 

 

Observer设计模式

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

 

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

 

 

 

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

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

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

3)热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。类似这样的例子是很多的,GOF对它进行了抽象,称为Observer设计模式:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其它依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。

 

使用委托和事件再做:

using System;

using System.Collections.Generic;

using System.Text;

 

namespace Observer

{

    class Heater

    {

        // 水温

        private int temperature;

 

        // Delegate

        public delegate void BoilWaterHandler(int param);

 

        // Event

        public event BoilWaterHandler BoilEvent;

 

        public void BoilWater()

        {

            for (int i = 0; i <= 100; i++)

            {

                temperature = i;

                if (temperature >= 95)

                {

                    if (BoilEvent != null)

                    {

                        BoilEvent(temperature);

                    }

                }

            }

        }

    }

 

    class Alarm

    {

        // 语音提示

        public void MakeAlert(int paraTemper)

        {

            Console.WriteLine("Alert: 现在水的温度是{0}", paraTemper);

        }

    }

 

    class Display

    {

        // 显示水水温

        public void ShowMsg(int paraTemper)

        {

            Console.WriteLine("Display: 现在水的温度是{0}", paraTemper);

        }

    }

 

    class MyObserver

    {

        static void Main(string[] args)

        {

            Heater ht = new Heater();

            Display dp = new Display();

 

            ht.BoilEvent += (new Alarm()).MakeAlert;

            ht.BoilEvent += dp.ShowMsg;

 

            ht.BoilWater();

        }

    }

}

 

Alert: 现在水的温度是95

Display: 现在水的温度是95

Alert: 现在水的温度是96

Display: 现在水的温度是96

Alert: 现在水的温度是97

Display: 现在水的温度是97

Alert: 现在水的温度是98

Display: 现在水的温度是98

Alert: 现在水的温度是99

Display: 现在水的温度是99

Alert: 现在水的温度是100

Display: 现在水的温度是100

Press any key to continue . . .

 

 

Dot Net Framework 中的委托与事件

 

.Net Framework的编码规范:

1)委托类型的名称都应该以EventHandler结束。

2)委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object类型,一个EventArgs类型(或继承自EventArgs)。

3)事件的命名为:委托去掉EventHandler之后剩余的部分。

4)继承自EventArgs的类型应该以EventArgs结尾。

 

再做一下说明:

1)委托声明原型中的Object类型的参数代表了Subject,也就是监视对象,在本例中是Heater(热水器)。回调函数(比如 AlarmMakeAlert)可以通过它访问触发事件的对象(Heater)。

2EventArgs对象包含了Observer所感兴趣的数据,在本例中是temperature

上面这些其实不仅仅是为了编码规范而已,这样也使得程序有更大的灵活性。比如说,我们不光想获得热水器的温度,还想在Observer端(警报器或者显示器)方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得麻烦,而如果我们将热水器的引用传给警报器方法,就可以在方法中直接访问热水器了。

 

using System;

using System.Collections.Generic;

using System.Text;

 

namespace ObserverFrameWork

{

    class Heater

    {

        // 水温

        private int temperature;

        // Heater Type

        public string type = "China - 888";

        // Heater Area

        public string area = "DL-LN";

 

        // Delegate

        public delegate void BoilWaterHandler(object sender, BoilWaterArgs e);

 

        // Event

        public event BoilWaterHandler BoilEvent;

 

        // Declare BoilWaterArgs

        public class BoilWaterArgs : EventArgs

        {

            public readonly int readTemperature;

 

            public BoilWaterArgs(int temperature)

            {

                this.readTemperature = temperature;

            }

        }

 

        protected virtual void BuildBoilEvent(BoilWaterArgs e)

        {

            if (BoilEvent != null)

            {

                BoilEvent(this, e);

            }

        }

 

        public void BoilWater()

        {

            for (int i = 0; i <= 100; i++)

            {

                temperature = i;

                if (temperature >= 95)

                {

                    BoilWaterArgs e = new BoilWaterArgs(temperature);

                    this.BuildBoilEvent(e);

                }

            }

        }

    }

 

 

 

 

    class Alarm

    {

        // 语音提示

        public void MakeAlert(object sender, Heater.BoilWaterArgs e)

        {

            Heater ht = (Heater)sender;

            Console.WriteLine("Heater Informaction:{0} ---{1} Alert: 现在水的温度是{2}", ht.area, ht.type, e.readTemperature);

        }

    }

 

    class Display

    {

        // 显示水水温

        public void ShowMsg(object sender, Heater.BoilWaterArgs e)

        {

            Heater ht = (Heater)sender;

            Console.WriteLine("Heater Informaction:{0} ---{1} Display: 现在水的温度是{2}", ht.area, ht.type, e.readTemperature);

        }

    }

 

 

 

 

    class Program

    {

        static void Main(string[] args)

        {

            Heater ht = new Heater();

            Display dp = new Display();

 

            ht.BoilEvent += (new Alarm()).MakeAlert;

            ht.BoilEvent += dp.ShowMsg;

 

            ht.BoilWater();

        }

    }

}

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12476590/viewspace-578385/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2007-12-21

  • 博文量
    257
  • 访问量
    498732