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

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

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

两种哲学

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

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

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

从继承到组合

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

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

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

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

后续

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

时间: 2024-11-18 23:53:34

C#动静结合编程之二: 两种哲学的相关文章

[转贴]基于UDP、TCP协议的C#网络编程之二

转自新浪"烈·翼·焚·天"的博客,原文地址:http://blog.sina.com.cn/s/blog_4c459776010009c3.html~type=v5_one&label=rela_nextarticle 第二截,讲讲基于TCP协议的网络编程,与UDP不同的是,基于TCP协议的编程的服务器端有一个监听对象:TcpListener,它负责监听来自客户端的消息并处理,并且必须在保持连接的情况下与客户端保持互动,下面举个例子,TCP不怎么复杂,只是综合要求较高,如果想编

实战JSP进阶编程之二:最简单的DAO

我们的第一个例子是简化的DAO方式,主要是在编程中引入了oop概念. 这次,我们将DAO补齐,但仍然保持最简单的形式,以便初学者学习. 简单的DAO模式构成: 1 interface 2. Factory 3 Implements 4. caller 第一个例子中的主程序NewsDAO.java代码没有改动,只是改了个名字, 成为implements. package news;import java.sql.*;public class NewsDAOMySQL implements News

Win7远程操作时提示“远程桌面服务当前正忙”两种解决方法

  Win7远程操作时提示"远程桌面服务当前正忙"两种解决方法           Win7系统远程桌面操作能够实现远程操控电脑,通过远程连接来进行一些控制,可是有些用户在进行远程连接的时候,输入账号密码无法进入,重新进入就会提示"由于远程桌面服务当前正忙,因此无法完成您尝试执行的任务",遇到这个问题该如何解决呢?下面小编给大家两种解决方法. 解决方法一 看一下你电脑任务管理器此项任务是否还在,如果在的话关掉就行了,很多时候是电脑没有反应过来造成的. 解决办法二 原

Win8系统下用户账户控制的两种开启方法

  下面小编就教大家如何开启win8系统中的用户账户控制功能. win8系统启用用户账户控制的方法: 第一种: 1.进入win8系统后,在传统桌面下按win+r键,输入msconfig,点击工具选项卡, 2.选择第二项更改UAC设置,点启动,选择通知的级别就行了,建议选择系统默认的第二个级别,确认,重启电脑.就启用啦! 第二种: 最直接简单得就是直接在页面上点击"启用用账户控制",出现界面,直接设置,确认重启,就可以启用账户啦! 以上小编介绍的两种方法都可以实现操作,大家都可以都试试的

win7手动创建桌面快捷方式的两种方法

  当用在安装一些应用程序时,通常程序会自动在桌面创建快捷方式,但也并非每个程序都为其创建快捷方式,故此想要在桌面中显示快捷方式,就需要手工进行创建,不过有很多人不知道如何创建,所以今天小编为大家带来了两种桌面创建快捷方式的操作方法,需要的用户赶快学习下吧! 操作步骤 方法一: 首先先打开程序的安装目录,如果发现有好几个和桌面上的图标一样的图标的话,我们一个一个打开,直到程序能打开了,就能确定是那个图标了,然后在对的图标上单击右键,选择"发送到"--"桌面快捷方式"

使用Java构造和解析Json数据的两种方法(详解二)_java

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包. 在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面接着介绍用org.json构造和解析Json数据的方法

两种php去除二维数组的重复项方法_php技巧

php去掉二维数组的重复值的方法总结,具体代码如下:方法一: //二维数组去掉重复值 function array_unique_fb($array2D){ foreach ($array2D as $v){ $v=join(',',$v); //降维,也可以用implode,将一维数组转换为用逗号连接的字符串 $temp[]=$v; } $temp=array_unique($temp); //去掉重复的字符串,也就是重复的一维数组 foreach ($temp as $k => $v){ $

C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)

上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容, 请阅读:http://www.cnblogs.com/yunfeifei/p/3922668.html. 下面我们来主要讲解一下MEF中的导入和导出,还是上一篇的代码(这篇中,我还会贴出完整的代码),修改Program的代码如下: using System; using System.Collections.Generic; using System.Linq; using Sys

两种PHP生成二维码的方法

  PHP生成二维码,个人认为最常用的有两种,1.使用google的api生成,2.使用PHP QR Code生成,两种方法生成的二维码都是很清淅的,效果不错.下面来分别说明这两种方法如何实现. 一.PHP使用google api在线生成二维码: 关于这个API的介绍就不说了吧,你可以去Google的官方网站查询,相信大家关注的是具体代码,如下: 1 2$urlToEncode="http://www.csdn.net";//要生成二维码的网址 3generateQRfromGoogl