C#中的委托和事件(5)
作者:JimmyZiYang 来源:蓝色理想 发布时间:2007-09-26 20:50:00
委托、事件与Observer设计模式
范例说明
上面的例子已不足以再进行下面的讲解了,我们来看一个新的范例,因为之前已经介绍了很多的内容,所以本节的进度会稍微快一些:
假设我们有个高档的热水器,我们给它通上电,当水温超过95度的时候:1、扬声器会开始发出语音,告诉你水的温度;2、液晶屏也会改变水温的显示,来提示水已经快烧开了。
现在我们需要写个程序来模拟这个烧水的过程,我们将定义一个类来代表热水器,我们管它叫:Heater,它有代表水温的字段,叫做temperature;当然,还有必不可少的给水加热方法BoilWater(),一个发出语音警报的方法MakeAlert(),一个显示水温的方法,ShowMsg()。
namespace Delegate {
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 param) {
Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:" , param);
}
// 显示水温
private void ShowMsg(int param) {
Console.WriteLine("Display:水快开了,当前温度:{0}度。" , param);
}
}
class Program {
static void Main() {
Heater ht = new Heater();
ht.BoilWater();
}
}
}
Observer设计模式简介
上面的例子显然能完成我们之前描述的工作,但是却并不够好。现在假设热水器由三部分组成:热水器、警报器、显示器,它们来自于不同厂商并进行了组装。那么,应该是热水器仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由警报器发出警报、显示器显示提示和水温。
这时候,上面的例子就应该变成这个样子:
// 热水器
public class Heater {
private int temperature;
// 烧水
private void BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;
}
}
}
// 警报器
public class Alarm{
private void MakeAlert(int param) {
Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:" , param);
}
}
// 显示器
public class Display{
private void ShowMsg(int param) {
Console.WriteLine("Display:水已烧开,当前温度:{0}度。" , param);
}
}
这里就出现了一个问题:如何在水烧开的时候通知报警器和显示器?在继续进行之前,我们先了解一下Observer设计模式,Observer设计模式中主要包括如下两类对象:
Subject:监视对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个监视对象,它包含的其他对象所感兴趣的内容,就是temprature字段,当这个字段的值快到100时,会不断把数据发给监视它的对象。
Observer:监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器和显示器,它们采取的行动分别是发出警报和显示水温。
在本例中,事情发生的顺序应该是这样的:
警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。
热水器知道后保留对警报器和显示器的引用。
热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。
类似这样的例子是很多的,GOF对它进行了抽象,称为Observer设计模式:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。
实现范例的Observer设计模式
我们之前已经对委托和事件介绍很多了,现在写代码应该很容易了,现在在这里直接给出代码,并在注释中加以说明。
using System;
using System.Collections.Generic;
using System.Text;
namespace Delegate {
// 热水器
public class Heater {
private int temperature;
public delegate void BoilHandler(int param); //声明委托
public event BoilHandler BoilEvent; //声明事件
// 烧水
public void BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;
if (temperature > 95) {
if (BoilEvent != null) { //如果有对象注册
BoilEvent(temperature); //调用所有注册对象的方法
}
}
}
}
}
// 警报器
public class Alarm {
public void MakeAlert(int param) {
Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
}
}
// 显示器
public class Display {
public static void ShowMsg(int param) { //静态方法
Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", param);
}
}
class Program {
static void Main() {
Heater heater = new Heater();
Alarm alarm = new Alarm();
heater.BoilEvent += alarm.MakeAlert; //注册方法
heater.BoilEvent += (new Alarm()).MakeAlert; //给匿名对象注册方法
heater.BoilEvent += Display.ShowMsg; //注册静态方法
heater.BoilWater(); //烧水,会自动调用注册过对象的方法
}
}
}
输出为:
Alarm:嘀嘀嘀,水已经 96 度了:
Alarm:嘀嘀嘀,水已经 96 度了:
Display:水快烧开了,当前温度:96度。
// 省略...
猜你喜欢
- ASPError Object 这个新增的,内置与ASP 3.0中的对象提供了一个以往版本中没有的专门用来处理错误的对象,这样,我们来操纵错
- 如果你计划将数据库从SQL Server 2000 升级到 SQL Server 2005。你在升级之前一定会测试每样东西,并且证明应用程序
- JavaScript中没有Trim函数,VBScript语言中才有这个函数,就是去掉字符串头和尾的空格。您可以访问这篇文章:《增加 java
- 原文:http://research.microsoft.com/~helenw/papers/subspace.pdfwindow.nam
- 错误15105,从网上找了一些解决方案,一般都是说文件的权限不足的问题,当然附加的时候必须是有数据库附加权限才可以操作的。解决办法1:给相应
- 一、备份数据库1、打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server2、SQL Server组-->
- 使用SQL Server事件探查器工具,你可用一个捕获到的跟踪来收集有关服务器的重要信息。与索引优化向导(Index Tuning Wiza
- 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第四个自然段。以下叙述的脚本包括服务器端脚本和客户端的脚本,服务器端脚本指在服务器上
- 利用系统crontab来定时执行备份文件,按日期对备份结果进行保存,达到备份的目的。1、创建保存备份文件的路径/mysqldata#mkdi
- 1:使用SHOW语句找出在服务器上当前存在什么数据库:mysql> SHOW DATABASES;2:2、创建一个数据库MYSQLDA
- 1、为什么淘宝的手机频道页面,竟然会有笔记本、数码相机、随身听,甚至是游戏之类的栏目,而且还有一个“数码·生活”栏目是包括以上这些设备的综合
- 有两个结构完全相同的表,由其中一个表插入另一个表中指定条件的数据,报如下错误: 仅当使用了列列表并且 IDENTITY_INSERT 为 O
- 今天突然想起做一个当鼠标经过<a/>时,会发出声音Js代码如下: <script type="text
- 【原文地址】My "First Look at Orcas" Presentation 【原文发表日期】 Th
- Silverlight和Flash,到底谁更强?谁更有优势?很多初接触Silverlight和Flash的人总是会问这个问题,因为它们在表面
- 经常会遇到这样一个情况:浏览器弹出对话框,提示脚本运行时间过长,询问“停止”还是“继续”。那究竟各个浏览器是如何判断在什么时候才弹出此对话框
- bookheader.asp Recommended Books for <%=session(&quo
- ASP长文章分页代码实例,也许你会问一篇文章为什么还要进行分页呢?因为文章有短有长,当你的文章很长的时候,如果就一个页面都显示出来的话,读者
- 可试试下面这个方法,但要保证在FORM中使用的Input Name都和数据库中使用的是一样的:upfiles.asp<% &
- 许多游戏玩家一定会对游戏中的动态鼠标指针有很深的印象,其实只要一句简单的CSS(层叠样式表),你也能在网页上实现这种效果。首先,你需要一个鼠