委托解释

我们出去吃饭,总是喜欢去人多生意好的馆子,因为这样的馆子往往味道和服务都比较好(相信群众),而那些生意冷清的馆子往往无人问津。生意好的馆子固然有其长处,但去这样地方就餐又总是需要先排队等位置,所以排号是比较流行的方式。当然,如果这家馆子的座位充足,就不需要排号,但是上菜又比较慢。无论怎样,如果厨房一时半会儿无法做好你的菜,那么你就只好耐心地等待,在这个时候你可以做自己的事情,跟朋友聊天、玩手机或者看美女,没有人会傻傻地站在厨房门口目不转睛地盯着厨师手中的锅铲直到做好自己的菜。

在软件开发工作中,我们也常常会遇到类似的问题,我们向某个服务器(或类似于服务器的东西)发送一个请求,需要获取到反馈信息后才能继续某项工作,但是如果这项工作不是最重要的或者目前唯一的工作项,我们完全没有必要让这个等待过程阻碍整个软件的使用,如果这样做了,那将获得非常糟糕的用户体验,就像我们看到有人一动不动地站在厨房门口等菜一样。

C#提供了委托机制来实现异步处理,也就是说,你向服务器发送请求以后就可以把精力用在做别的事情上,服务器返回请求后应用程序会自动调用你之前安排好的方法来处理接下来的工作。换句话说,你点好了菜,接下来就可以和朋友聊天,厨房做好了菜无论是叫号还是由服务员端到你桌上来,反正不用你再操心了。

下面我们先创建一个顾客类:

   1: public class Customer
   2: {
   3:     public int ID { get; private set; }
   4:  
   5:     public Customer(int id)
   6:     {
   7:         this.ID = id;
   8:     }
   9: }

在这个场景中,我们不需要赋予Customer类太多属性,我们假设这家餐馆采用的方式是叫号而不是由服务员把菜端到每个顾客桌上,所以Customer类只要有个ID号就够了。

接下来我们来实现这个叫号的方法,虽然很简单,但是肯定不是只有一家餐馆采用这种方式,因此我们把这个方法放在单独的一个类里面:

   1: public class DelegateDemo
   2: {
   3:     public static void CallCustomer(Customer customer)
   4:     {
   5:         if (customer != null)
   6:         {
   7:             Console.WriteLine("Customer ID: " + customer.ID);
   8:         }
   9:     }
  10: }

然后我们来创建最重要的类,餐厅类:

   1: public class SampleRestaurant
   2: {
   3:     public List<Customer> Customers { get; private set; }
   4:  
   5:     public SampleRestaurant()
   6:     {
   7:         this.Customers = new List<Customer>();
   8:  
   9:         for (int index = 1; index <= 10; index++)
  10:         {
  11:             Customers.Add(new Customer(index));
  12:         }
  13:     }
  14:  
  15:     public delegate void EnumCustomerCallback(Customer customer);
  16:  
  17:     public void EnumCustomers(EnumCustomerCallback callback)
  18:     {
  19:         foreach (var customer in Customers)
  20:         {
  21:             callback(customer);
  22:         }
  23:     }
  24: }

在这个餐厅类里面,有一个顾客的集合,表示当前餐厅里所有的顾客,我们先往这个集合里面塞10个顾客进去以备待会儿叫号。然后我们在这个类里面声明了一个委托EnumCustomerCallback,并限定了它的函数签名。要使用这个委托的函数就必须符合该委托的签名形式。例如,该餐馆采用叫号的方式,也就是说我们要把DelegateDemo.CallCustomers方法传递给EnumCustomerCallback委托,因此它俩的函数签名是一致的。然后我们还定义了一个EnumCustomers方法,该方法的以EnumCustomerCallback委托为参数。该方法执行的内容是挨个遍历当前所有顾客,至于遍历到每个顾客是采取什么样的方式,叫号还是有服务员端菜呢,取决于传递给当前委托的方法来执行。

好,接下来我们来执行这段代码看看效果:

   1: static void Main(string[] args)
   2: {
   3:     SampleRestaurant restaurant = new SampleRestaurant();
   4:     SampleRestaurant.EnumCustomerCallback callCustomer
   5:         = new SampleRestaurant.EnumCustomerCallback(DelegateDemo.CallCustomer);
   6:     restaurant.EnumCustomers(callCustomer);
   7:  
   8:     Console.ReadLine();
   9: }

在这段代码的第4行,我们创建了一个委托实例callCustomers,并把叫号的方法DelegateDemo.CallCustomers传递给它座位该餐馆上菜的方式。然后我们再把这个方式传递给该餐厅的遍历顾客的方法,让它在遍历到每个顾客的时候采用老板设定好了的方式去执行。

下面的截图就是以上代码执行的结果,喇叭里挨个叫出顾客的编号,通知他们去取餐:

接下来我们来介绍一下事件机制,之所以把事件放在委托后面讲,是因为事件是在委托的基础上实现的。这一次我们站在厨师的角度来看待什么是事件。

作为一个厨师,炒菜是最基本的工作内容,而对于餐厅的服务员来说,可以拿着点菜单去叫厨师来炒菜,因此这就存在一个观察者模式,即发布和订阅的机制。服务员发布说:“顾客要个青椒肉丝”,厨师订阅说:“行,我马上炒个青椒肉丝”。定义事件需要注意的是,事件需要两个参数,一是引发该事件的对象,本例中是负责点菜的服务员;二是事件消息对象。其中,事件消息对象必须派生自System.EventArgs类。

因此我们先来设计一个点菜单作为事件消息类:

   1: public class OrderEventArgs : EventArgs
   2: {
   3:     public string DishName { get; set; }
   4:     public int Amount { get; set; }
   5: }

在这个点菜单中,我们只包含了菜名和数量,因为对于厨师来说,他只要知道这两个基本信息就够了。接下来我们来定义这个厨师类:

   1: public class Cook
   2: {
   3:     public Waitress TheWaitress { get; private set; }
   4:  
   5:     public Cook(Waitress waitress)
   6:     {
   7:         this.TheWaitress = waitress;
   8:         this.TheWaitress.OnOrderHandler += new Waitress.OrderEventHandler(waitress_OnOrderHandler);
   9:     }
  10:  
  11:     void waitress_OnOrderHandler(object sender, OrderEventArgs e)
  12:     {
  13:         Console.WriteLine("I cook " + e.Amount + " " + e.DishName + ".");
  14:     }
  15: }

在厨师类中包含了一个Waitress对象,这表示发布者,也就是叫厨师炒菜的服务员。第8行,厨师把自己添加进预订者列表,也就是说在服务员下单子的时候,厨房里得有现成的厨师才行,如果厨房里没有厨师,服务员发布了点菜事件也没人接招。

然后我们来看看事件的发布者,服务员:

   1: public class Waitress
   2: {
   3:     public delegate void OrderEventHandler(object sender, OrderEventArgs e);
   4:     public event OrderEventHandler OnOrderHandler;
   5:  
   6:     public void Order(string dishName, int amount)
   7:     {
   8:         if (String.IsNullOrEmpty(dishName) || amount <= 0)
   9:         {
  10:             return;
  11:         }
  12:  
  13:         OrderEventArgs orderEventArgs = new OrderEventArgs { DishName = dishName, Amount = amount };
  14:  
  15:         if (OnOrderHandler != null)
  16:         {
  17:             OnOrderHandler(this, orderEventArgs);
  18:         }
  19:     }
  20: }

在这个服务员类里面,我们首先定义了一个带有两个参数的委托以及一个事件。委托的两个参数一个是发布者对象,另一个是事件信息对象。然后,服务员类还提供了一个点餐方法,点餐方法创建一个事件信息类(点菜单),如果事件的订阅者不为空,也就是说厨房里目前有厨师,那么服务员就会把这个点菜单发送过去,而事件的订阅者会有专门的方法来处理这个事件。

   1: static void Main(string[] args)
   2: {
   3:     Waitress waitress = new Waitress();
   4:     Cook cook = new Cook(waitress);
   5:  
   6:     waitress.Order("QingJiaoRouSi", 1);
   7:  
   8:     Console.ReadLine();
   9: }
时间: 2024-09-04 12:07:09

委托解释的相关文章

html5与css3面试题(2)

10.xhtml与HTML的区别? Html是对web网页设计的语言,而xhtml是基于xml的置标语言 11.面向对象的引用方法分为几种? 内部写的 原型链引用的 12.什么是重载? 函数名相同,但参数不同,所以就会调用不同的方法,javascript不支持重载,但是可 以用arguments模拟重载. 13.说一说arguments对象? arguments是一个特殊的对象可以给它看成数组,因为它的获取是通过下标去获取. 可以用arguments.length来判断传入参数多少来调用函数,达

[第二家公司]收藏夹

<!DOCTYPE NETSCAPE-Bookmark-file-1> <!-- This is an automatically generated file. It will be read and overwritten. Do Not Edit! --> <TITLE>Bookmarks</TITLE> <H1>Bookmarks</H1> <DL><p> <DT><H3 FOLDED

委托的最佳科普解释

转:http://www.cnblogs.com/liulun/archive/2013/02/26/2909985.html 委托 delegate Boolean moreOrlessDelgate(int item); class Program { static void Main(string[] args) { var arr = new List<int>() { 1, 2, 3, 4, 5, 6,7,8 }; var d1 = new moreOrlessDelgate(Mor

.NET基础 (15)委托

委托1 请解释委托的基本原理2 委托回调静态方法和实例方法有何区别3 什么是链式委托4 链式委托的执行顺序是怎么样的5 可否定义拥有返回值的方法的委托链6 委托通常可以应用在哪些场合 委托1 请解释委托的基本原理 委托是一个钟数据类型,用来传递方法.委托类型继承自System.Delegate,自定义委托类型都直接继承自System.NulticastDelegate,System.NulticastDelegate又继承自System.Delegate.每个委托至少包含一个指向某个方法的指针,

JavaScript事件代理和事件委托

一.概述: 那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象,我仔细揣摩了一下,这个例子还真是恰当,我就不去想别的例子来解释了,借花献佛,我摘过来,大家认真领会一下事件委托到底是一个什么原理: 有三个同事预计会在周一收到快递.为签收快递,有两种办法:一是三个人在公司门口等快递:二是委托给前台

关于C#委托应用与总结

什么是委托? 官方解释 委托是一种定义方法签名的类型.当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法.   个人理解 委托是一个持有一个或多个方法的对象,并且该对象可以被执行,可以被传递 使用方法   首先创建一个类或多个类并且创建方法有无参数都可以 使用关键字 delegat 创建委托 实例化类 使用委托类创建委托对象并且为对象赋值 赋值内容为类的方法用对象名和"+"这个符号可以持有多个方法 调用委托  调用方式与函数类同 笔者在这里用案例写

[转载]C#深入分析委托与事件

原文出处: 作者:风尘浪子 原文链接:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html 同类链接:http://www.cnblogs.com/SkySoot/archive/2012/04/05/2433639.html 引言 本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C# 当中事件(Event)的由来,它能使处理委托类型的过程变得更加简单.还将为您解释委托的协变与逆变,以及如何使用 Deleg

JavaScript事件委托的技术原理

如今的JavaScript技术界里最火热的一项技术应该是‘事件委托(event delegation)’了.使用事件委托技术能让你避免对特定的每个节点添加事件监听器:相反,事件监听器是被添加到它们的父元素上.事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件.基本概念非常简单,但仍有很多人不理解事件委托的工作原理.这里我将要解释事件委托是如何工作的,并提供几个纯JavaScript的基本事件委托的例子. 假定我们有一个UL元素,它有几个子元素: <ul id="parent-l

C#综合揭秘——深入分析委托与事件

本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C# 当中事件(Event)的由来,它能使处理委托类型的过程变得更加简单.还将为您解释委托的协变与逆变,以及如何使用 Delegate 使 Observer(观察者)模式的使用变得更加简单.在事件的介绍上,会讲述事件的使用方式,并以ASP.NET的用户控件为例子,介绍一下自定义事件的使用.最后一节,将介绍Predicate<T>.Action<T>.Func<T,TResult>多种泛型委托的使用和Lamb