WEB开发网
开发学院软件开发C语言 C#动静结合编程之二: 两种哲学 阅读

C#动静结合编程之二: 两种哲学

 2009-03-17 08:19:02 来源:WEB开发网   
核心提示:在本系列的上一篇中,谈到了接口和委托语法约束强度的比较,C#动静结合编程之二: 两种哲学,我的结论是接口的语法约束要强于委托,这个话题得到了不少朋友的关注和讨论,必须根据领域建模需要把握分寸,后续下一篇,对此,我在综合反馈

在本系列的上一篇中,谈到了接口和委托语法约束强度的比较,我的结论是接口的语法约束要强于委托。这个话题得到了不少朋友的关注和讨论。对此,我在综合反馈,查阅资料,加上自己的理解的基础上对接口和委托的关系进行一个小小的总结,并借此推动本篇的介绍。

一方面,从OO角度看,接口和委托是实现多态性的两种手段;另一方面,从软件设计角度看,接口和委托是将规范与实现分开从而面向抽象编程的两种手段。因此,就存在的意义而言,接口和委托有着重要的联系。虽然委托不能覆盖接口所有的功能,关于语法约束强度的比较没有全面的说服力,但我们明显能体会到委托比接口更加灵活。

两种哲学

这里尤其值得注意的是接口和委托所代表的两种哲学:继承哲学和鸭子哲学。继承哲学关注对象继承结构,即“你继承什么你就是什么”;鸭子哲学关注对象的性质,即“你能做什么你就是什么”。PS:“鸭子哲学”的名称来源于Duck Typing的相关论述“如果一只动物,走起来像鸭子,叫起来像鸭子,那我可以把它当鸭子”。

需要强调的是,继承哲学不止体现在接口上,鸭子哲学也不只体现在委托上。而两种哲学,也各有优势,各有适用场合,没有高下,这里只为看清它们的差别,以灵活运用。

让我们先来看一个例子:对体育进行领域建模,这里我们只关注教练和队员的建模。

从继承到组合

按继承哲学的方法论”是什么就应该继承什么”,我们很容易想到定义IPlayer,ICoach等接口,让队员继承(实现)IPlayer,让教练继承ICoach。一般情况下,这本来没有什么问题,但考虑到对象生命周期这个关键因素,情况就可能有所不同。比如,我们知道刘国梁原来是乒乓球队员,后来当上了教练,要表达刘国梁从队员到教练的转变就不那么容易。因为,C#是静态类型语言,继承关系是在编译时确定的,无法在运行时删除继承关系(刘国梁退役),也无法在运行时增加继承关系(刘国梁当教练)。如果要勉强认为队员刘国梁和教练刘国梁是两个对象也是可以的,不过这必然影响领域模型的表达是否自然。

很多有经验的朋友可能已经意识到:C#中继承是很强的静态约束,如果领域模型足够复杂,在对象生命周期内,其具有的行为可能会发生变化,那么必须慎用继承。

用组合代替继承是增加模型灵活性的常见手段,一般方法是将行为抽象为行为类/接口/委托,比如:定义IPlay,ITeach行为接口,并为对象增加行为属性Play和Teach。虽然组合关系在C#中也是无法动态增加和删除的,但可以采取折衷的方式,具体到上面的例子,对象整个生命周期内都必须具有Play和Teach的行为属性,并且通过抛出运行时异常来表达对象还不具备某种行为。

继承到组合的转变在一定程度上显示了鸭子哲学的灵活性。实际上,所谓“行为”正是“能做什么”。通过上面的例子不难发现,组合关系通过把焦点从“继承什么”转移到“能做什么”获得了更大的灵活性。这个转变一点儿不勉强,很自然,很符合领域的本质。虽然,C#中组合关系也是静态的,但已经比继承具有了更多的动态元素,而动态和静态本身没有优劣,必须根据领域建模需要把握分寸。

后续

下一篇,我将重点介绍鸭子哲学更纯正的体现:Duck Typing,敬请关注!

系列文章:

C#动静结合编程之一: 接口和委托的约束强度

Tags:动静 合编 程之二

编辑录入:爽爽 [复制链接] [打 印]
    赞助商链接