分享
 
 
 

Henry手记—使用Template Method设计模式的.NET事件处理机制(一)

王朝c#·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Henry手记—使用Template Method设计模式的

.NET事件处理机制(一)

By Kevin McFarlane

Henry译(2002.10.14)

[Henry注:本文并不复杂,可以为.net事件处理的中级读物。本文虽为翻译,但并不是完全精确之译文,加入了Henry自己的看法,如有谬误,责任在Henry矣]

1. 引言

Microsoft .NET事件处理,和标准的面向对象架构一样,使用的是著名的Observer设计模式(请参看书籍《设计模式(Design Patterns)》, Gamma et al., Addison-Wesley, 1995, pp325-330)。本文描述了如何利用Template Method(Henry注:模板方法,总觉得不翻出来更亲切)设计模式去增强.NET的事件处理机制。讨论与代码片断是基于C#的,但结论示例是使用了C#和Visual Basic.NET分别实现的。

本文讨论的思想是出自于Tomas Restrepo在2002年3月出版的《Visual Systems Journal》,该文是基于MicrosoftMSDN Library的.NET专题提供的标准事件处理示例:《 Design Guidelines for Class Library Developers》 (详见文中的 "事件使用向导"一节)。

对于事件处理,最简单的设计就是如何触发一个事件,而不是关心谁来执行它,或不同的使用者是否需要用不同的方法来关联它。

2. 示例—简单的事件处理

设有这样一个类:Supplier,当它的name成员被设置就会触发一个事件,而类Client就用于处理它。

public class Supplier

{

public Supplier() {}

public event EventHandler NameChanged;[H]

public string Name

{

get { return name; }

set { name = value; OnNameChanged(); } [H]

}

private void OnNameChanged()

{

// 在注册后,使用者即可触发此事件

if (NameChanged != null)

NameChanged(this, new EventArgs());

}

private string name;

}

public class Client

{

public Client()

{

// 为 supplier 事件注册

supplier = new Supplier();

supplier.NameChanged += new EventHandler( _

this.supplier_NameChanged); [H]

}

public void TestEvent()

{

// 设置Name,产生一个事件

supplier.Name = "Kevin McFarlane";

}

private void supplier_NameChanged(object sender, _

EventArgs e) [H]

{

// 处理supplier事件

}

private Supplier supplier;

}

[Henry注:在此示例中,我们同时可以学习一下在C#中自定义一个事件,并处理它的方法。请注意我标上[H]的代码]。

一个事件的使用者即可以是外部的,也可以是内部的。

一个“外部的”使用者是指可以执行一个事件,但与触发此事件的类并无关系。换句话说,它不是事件类继承树中的一部分。示例中的Client类就是一个外部使用者。

一个“内部的”使用者可以是事件发生类自身(如果它同时处理自已的事件的话),或是该事件发生类的一个派生类。对于这种情况,上文所说的简单的设计就不够充分了。用户不能很方便地改变当事件被触发后要发生的变化,或是处理事件的默认行为了。

为了应付这个问题,在.NET Design Guidelines for Class Library Developers一文中,Microsoft推荐使用一个保护的Virtual Method(虚方法)去触发每个事件。这就提供给子类一个通过重写来处理事件的方法。因此,在我们的示例中,OnNameChanged()应该象下例这样写:

protected virtual void OnNameChanged()

{

// 在注册后,使用者即可触发此事件

if (NameChanged != null)

NameChanged(this, new EventArgs());

}

Microsoft随即说:“派生类在处理OnEventName时(Henry注:OnEventName即类似于OnNameChanged的事件触发方法),可选择不调用基类。要这么做就得在OnEventName方法中不包含任何处理过程以利于基类正确地工作。”

这有一个问题,一般来说,OnNameChanged()在触发事件前可以做一些默认的处理。重写OnNameChanged()可以实现不同的处理过程。但是为保证外部的使用者工作正常,它必须调用基类。如果它不能调用基类,该事件就不能为外部使用者所用。忘记调用触发事件的基类,就违背了Liskov的多态替代原则(Henry注:出自麻省理工学院(MIT)计算机科学实验室的Barbara Liskov女士发表的经典文章Data Abstraction and Hierarchy,本文原作者做了小改动):使用指向基类的引用的方法,必须能够在不知道具体派生类对象类型的情况下使用它们。幸运的是,现在有一个解决的方法。

3. Template Method设计模式

Template Method设计模式的目的是定义一个算法作为固定的操作步骤,但有一个或多个步骤可以有变化。(Henry注:变化通常是指将某些步骤延迟到子类中去描述与执行)在我们的示例中,算法可认为是由触发事件及其响应来组成。需要有变化的地方就是响应。因此决窍就在于将它从事件触发中分离出来。我们将OnNameChanged()分割成两个方法:InternalOnNameChanged() 和OnNameChanged()。InternalOnNameChanged()调用OnNameChanged()来执行默认的处理,然后触发事件。

private void InternalOnNameChanged()

{

//派生类可重写默认的行为

OnNameChanged();

// 在注册后,使用者即可触发此事件

if (NameChanged != null)

NameChanged(this, new EventArgs());

}

protected virtual void OnNameChanged()

{

//在此执行默认的行为

}

Name属性改为:

get { return name; }

set { name = value; InternalOnNameChanged(); }

使用这种方法的好处在于:

1) 在这个触发事件的示例中,它是基类执行的重要步骤以避免派生类调用基类执行的失败。因此外部使用者可以获得更为可靠的服务;

2) 派生类可毫不用担心,在OnNameChanged()中安全地替换基类的默认行为。

e-mail: ruigeren@sina.com

QQ: 18349592

----

声明:本文版权与解释权归韩睿所有,如需转载,请保留完整的内容及此声明。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有