c#中的委托、事件、Func、Predicate、Observer设计模式以及其他
2011-02-26 20:37
701 查看
转载自遇见472405746
最终编辑weblogical
最终编辑
参考资料: 1. 2. 3. 4. 5. 6. 7. 8. 事件的一个综合性的例子: 说明:由于本文内容比较杂,前边的叙述部分只是破碎条目的聚合,没有逻辑连贯性。请仔细阅读最后的observer设计模式范例的注释,一切尽在注释中了。委托委托保持方法的引用只有与某委托具有相同签名的方法才能被该委托引用。 委托示例一://定义一个委托,该委托的签名是:返回int,接受两个参数,一个string一个bool delegateintSomeDelegate(strings,boolb); //实例化这个委托。 ClassMyClass{ [code] //定义一个函数,该函数与SomeDelegate委托具有相同的签名。 privatestaticintSomeFunction(stringstr,boolbln){ //Dosomethinghere. } publicstaticvoidmain(){ sd=newSomeDelegate(SomeFunction);//给委托赋值方法之一 sd=SomeFunction;//匿名委托,直接用方法名赋值,不用先new一个SomeDelegate sd+=SomeFunction;//对委托绑定方法 sd+=newMyClass().SomeFunction2;//非静态方法。 } } [/code] 匿名委托的常见例子:this.button1.Click+=newEventHandler(button1_Click);但有时候我们也可以匿名地写成这样: this.button1.Click+=button1_Click; 委托的一些总结:使用+=进行绑定之前必须先使用=给委托赋值,否则会出现“使用了未赋值的局部变量”的编译错误。"可以将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其绑定的方法。 不管之前这个委托绑定了多少函数,只要一进行赋值,原来绑定的和赋值的方法都被冲掉了。 在委托被赋值(值为某个函数名)之后,程序中凡是该函数名出现的地方,都可以用这个委托代替。 委托示例二:classProgram 事件用C语言写一个“事件”的模拟程序Example.c //定义一个函数指针func int(*func)(void); //调用该函数相当于触发了事件。 //该事件触发后,会检查函数指针func是否为NULL,如果不为NULL,说明该指针已被赋值(相当于该事件被注册)。 //如果事件已被注册,则执行之。 voidfireTheEvent(){ if(func!=NULL){ func(); } } voidregisterTheEvent(int(*function)(void)){//为fireTheEvent事件注册监听器。 func=function; } intcallBack(){ printf("Hello~thisisacallBack/n"); } intmain(){ registerTheEvent(add);//注册事件监听,回调函数为callBack。 fireTheEvent();//触发事件。由于已注册过监听,所以事件一旦触发就会调用callBack函数. } 事件只能用"+="或"-=",这有效地防止了在委托已被其他函数绑定时由于误用=而导致的委托调用链被清空。 event前边的访问修饰符只决定谁能够注册(或说监听)它,并不决定谁能够调用它。就调用来说,无论event声明时有没有public关键字,事件本身都会被编译成private,然后编译器会编译出来两个方法,分别是add和remove,当你用"+="对事件进行绑定时,其实编译器是在调用add方法。而add方法和remove方法的访问限制是由声明事件时候的访问限制符决定的。 因此永远只有声明它的那个类可以调用它,其他类与事件的交互只能通过"+="和"-="。这意味着即使它的子类也不能通过直接调用的方式触发事件。为了使其他类能够触发这个事件,我们可以在声明该事件的类中加一触发该事件的公开方法。当然,如果你希望子类能够重写触发的过程,那么你完全可以把这个公开的方法搞成virtual的。 而普通的委托(delegate)相当于一个字段,声明时候的访问限制符完全决定了委托的访问限制属性。 此处比较拗口,请阅读observer模式范例中的注释。 委托与事件的区别1.事件可以被包含在接口的声明中,委托不可以.例子: delegatevoidMsgHandler(strings); interfaceITest { eventMsgHandlermsgNotifier;//compiles MsgHandlermsgNotifier2;//errorCS0525:Interfacescannotcontainfields } classTestClass:ITest { publiceventMsgHandlermsgNotifier;//Whenyouimplementtheinterface,youneedtoimplementtheeventtoo staticvoidMain(string[]args){} } 2. Eventsaremarkedassuchinthemetadata.ThisallowsthingsliketheWindowsFormsorASP.NETdesignerstodistinguisheventsfrommerepropertiesofdelegatetype,andprovideappropriatesupportforthem(specificallyshowingthemontheEventstabofthePropertieswindow). 3. 习惯上: 委托在功能上常被用作“函数指针”,常作为某函数的输入。 事件在功能上常被用于:订阅消息。 delegate和Delegate的差别而Delegate是System.MulticastDelegate的父类。delegate仅仅是C#的关键字,表示一个继承自System.MulticastDelegate的具体委托类 Delegate和System.MulticastDelegate都是抽象类,只有编译器才可以从此类派生。也就是说,除了用delegate这种形式,我们不能显式地从Delegate和System.MulticastDelegate这两个类派生。 匿名方法与Labmda表达式例子:classProgram { delegatevoidD1(); delegatevoidD2(stringmyName); staticvoidMain(string[]args) { //正常赋值 D1d1=newD1(HelloWorld1); d1(); //用匿名方法给委托赋值 staticvoidHelloWorld1() } Lambda表达式可以添加多行语句 (Str1,str2)=>{ Console.WriteLine("哈哈~"); Returnstr.EndsWith(str2); } Lambda表达式若没有参数,则可以用一个空括号来代替。 Action和Func和PredicateAction、Func、Predicate本质上都是委托Action是无返回值的泛型委托 Action表示无参,无返回值的委托 Action<int,string>表示有传入参数int,string无返回值的委托 Func是有返回值的泛型委托 Func<int>表示无参,返回值为int的委托 Func<object,string,int>表示传入参数为object,string返回值为int的委托 Predicate是返回bool型的谓语泛型委托 Predicate<int>表示传入参数为int返回bool的委托 Action示例:classProgram Func示例:classProgram Observer设计模式Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式主要包括如下两类对象: Subject:被监视对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个被监视对象,它的temprature字段就是其他对象感兴趣的内容,当这个字段的值大于95时时,会不断把数据发给监视它的对象。 Observer:监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器和显示器,它们采取的行动分别是发出警报和显示水温。 假设热水器由三部分组成:heater(热水器)、alarm(警报器)、display(显示器),它们来自于不同厂商并进行了组装。那么,应该是heater仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由alarm发出警报、display显示水温。 怎么实现“水烧开时,heater通知alarm和display”呢。我们通过“事件”来实现。 范例:usingSystem; 但这个范例不符合.netframework规范。符合.net规范的应该是 委托类型的名称都应该以EventHandler结束。委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object类型(代表了产生该事件的那个对象的引用),一个EventArgs类型(事件产生时候传递的参数)。 这些不仅仅是为了编码规范,也使得程序有更大的灵活性。比如说,如果我们不光想获得热水器的温度,还想在Observer端(警报器或者显示器)方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得很麻烦,而如果我们将热水器的引用传给警报器的方法,就可以在方法中直接访问热水器了,也就不用在参数e中传递过多的信息了。 符合.net规范的observer模式范例:usingSystem; //当事件触发时,就把this当sender传递出去,是的当初注册这个事件的对象能够通过sender拿到当前heater的引用。 //而e中包含了当事件被触发时,heater想要向外界传递出去的信息。本例中只有此时的温度。 来源 |
相关文章推荐
- c#中的委托、事件、Func、Predicate、Observer设计模式以及其他
- c#中的委托、事件、Func、Predicate、Observer设计模式以及其他
- [学习笔记]c#中的委托、事件、Func、Predicate、Observer设计模式以及其他
- c#中的委托、事件、Func、Predicate、Observer设计模式以及其他
- C#中的委托和事件(提及Observer设计模式)(转载)
- C#,由委托到Observer设计模式,再到事件机制
- C# 中的委托和事件与Observer设计模式
- C#中的委托和事件(5)---委托、事件与Observer设计模式
- 转载:C#中委托、事件与Observer设计模式
- C#,由委托到Observer设计模式,再到事件机制
- C#设计模式之十九:Observer模式(使用委托、事件)
- C# 中的委托和事件_Observer设计模式[转]
- C#中的委托和事件--5.委托、事件与Observer设计模式
- C# 中的委托和事件 以及观察者模式
- 实现范例的Observer设计模式 事件 委托
- C# 中的委托和事件 以及观察者模式
- 委托、事件与Observer设计模式
- C# ~ 从 委托事件 到 观察者模式 - Observer
- 初识c#---委托,事件和观察者模式(Observer)设计模式
- Observer设计模式——委托事件