文章目录

委托和接口都允许类设计器分离类型声明和实现。任何类或结构都能继承和实现给定的接口。可以为任何类上的方法创建委托,前提是该方法符合委托的方法签名。
    接口引用或委托可由不了解实现该接口或委托方法的类的对象使用。既然存在这些相似性,那么类设计器何时应使用委托,何时又该使用接口呢?
在以下情况下,请使用委托:

  • 当使用事件设计模式时。
  • 当封装静态方法可取时。
  • 当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。
  • 需要方便的组合。
  • 当类可能需要该方法的多个实现时。

在以下情况下,请使用接口:

  • 当存在一组可能被调用的相关方法时。
  • 当类只需要方法的单个实现时。
  • 当使用接口的类想要将该接口强制转换为其他接口或类类型时。
  • 当正在实现的方法链接到类的类型或标识时:例如比较方法。

    使用单一方法接口而不使用委托的一个很好的示例是 IComparable 或泛型版本 IComparable<(Of <(T>)>)。IComparable 声明 CompareTo 方法,该方法返回一个整数,指定相同类型的两个对象之间的小于、等于或大于关系。IComparable 可用作排序算法的基础。虽然将委托比较方法用作排序算法的基础是有效的,但是并不理想。因为进行比较的能力属于类,而比较算法不会在运行时改变,所以单一方法接口是理想的。看了上面这段精要而且简短总结(来自微软官方),初学者是不是觉得不知所云。但是当你对接口与委托有深入了解与实践之后觉得上面的话是多么的简单明了,真可谓是一针见血,说得恰到好处。上面的设计总结,揭示以下相关内容:

  1. Observer 模式[GoF]
  2. 事件设计模式
  3. 接口多态

    很显然,如果大家对observer模式有熟悉的话,那么对.net或java的事件设计模式应该非常容易理解。observer模式主要用于解决一对多的类似于发布与订阅这样的场景。像java的所有Listener,.net的所有event方法订阅者。从名字上来看,不管是监听者,还是订阅者,其实都是观察者,它们都是用来监视或订阅或观察别人(被观察者observerable)的一举一动的。只要别人有什么动作或变化,它observer就马上作出反应。所以,”当使用事件设计模式时“,自然就想到用委托来实现,而且.net平台用它来实现observer(需要方便的组合),可谓更加简洁,更加解藕。”当类可能需要该方法的多个实现时”,我们来看看委托只是声明了一个方法原型(prototype),可以说成是一个方法的模板(eg.:public delegate void Action(T t))。也就是一个方法有多个实现,大家不要与方法重载(overloading)搞混了,重载方法其实已经是另一个方法与另一个实现,只是方法名还是相同的。
    委托只是指定一个方法原型,只是所有与原型匹配的方法都是合理的实现,其实接口也这样,指定一个方法的原型(注意,接口与委托在方法签名的差别)。显然,委托是方法的1对N关系,当然也可以1对1,其实应该可以是M对N关系。而接口是方法的N对1关系(当存在一组可能被调用的相关方法时),即一组方法对应一个接口(类),
而且每个方法所在的类只需要方法的单个实现时。这就是为什么“当使用接口的类想要将该接口强制转换为其他接口或类类型时”建议使用接口而不使用委托。那么这时候,你也许会问,如果我定义一个接口里只有一个方法,然后写N个接口的实现者,不一样可以达到像委托那样方法的1对N关系?呵呵,不错,确实是这样,大家看看java,其实没有委托(delegate)关键字,它所有的事件模型实现,都是使用ActionListener方式。的确在事件模型实现上,像java中的接口方式与.net的delegate方式都是可以。其实它们正在observer模式的两种不同实现方式而已。
    其实,.net也可像java那种方式来实现,当然.net的委托还有其它作用,如异步调用(BeginInvoke),回调函数(Callback),lamada表达式等都应用到委托。

文章目录