接口实现映射vs基类继承映射
目前的ORM方案,似乎比较少讨论到一个OOD中非常重要的方面——接口。当绝大多数ORM事先都能较好的映射常见的单根继承关系时,却往往忽略(回避?)了接口的地位。
注,这里的接口因为主要是讨论实体定义,因此,不涉及包含方法定义的接口,这里只关注包含需要持久化的实体属性接口。
我们知道,实现一个接口和继承一个基类是不同的OO语义。实现接口意味着一个类宣告遵守接口描述的契约,这就意味着,每个实现接口的类,必须,自己负责接口的实现。而继承一个基类代表不仅遵守基类宣告的契约,而且直接重用基类的实现(当然,需要的话也可以过在基类的部分或全部实现)。
前面我们已经讨论了各种常见的ORM中的继承体系映射方案,我们会发现,单从映射的灵活性,自然程度来讲,一实体一扩展表方案无疑最自然。分析其原因,是因为,它就和我们在OO中定义继承体系中的类一样,子类只需定义扩展的部分,无需重复包含父类已经定义的属性。
OK,那么,和基类继承映射相比,接口处在一个什么地位呢?
首先,我们发现,接口是一个抽象类,因此,不想具体的实体类那样需要持久化,因此,接口不像具体的实体类那样需要对应一张表。
其次,接口描述的是一种契约,换句话说,以仅仅包含属性的接口为例,假设有一个包含字段A,B的接口,那么,一个实体继承这个接口,意味着,这个实体对应的数据表包含相同类型的A,B字段。
不知道同学们发现没有,此时出现的情况和一实体一具体表的情况有点相似。尽管子类继承一个接口(一个抽象基类),但是,每个实现接口的子类实际上重复包含了接口中定义的字段属性,区别是,此时因为基类是接口,不需要持久化,因此,不会有一实体一具体表那样的的数据冗余。
一直没有看到其他的ORM实现了利用接口来描述的共享字段契约(也可能是我孤陋寡闻^-^),也许是大多数ORM使用具体类而不是接口来描述实体的定义。
在NBear中,由于采用接口来定义实体,当然,就可以很方便的用接口来定义字段共享契约。
那么,采用接口来定义字段共享契约有什么用呢?
仅仅接口定义实体方式下,在定义实体的时候不用像具体类实现接口那样每个类实现一边接口那样要多打一些代码,那么,还不足以说明接口定义字段共享契约的意义。
接口定义字段共享契约真正的意义在于,它能够引导我们更好的设计和映射我们的OO系统。我们常常发现,当按照传统的单继承的思路来设计继承体系时,尤其是,当脑袋中一直包含着让模型更适合使用ORM框架来持久化时,我们往往会忽略接口,而过度依赖基类继承。
举例来说,在双鱼座的最近一篇Blog中,他举了一个User和UserGroup都可以拥有权限的例子。他的实现方案是,让User和UserGroup都从一个PrivilegeOwner类继承。在这样的实现下,如果我要实现将User分为两类,一类可以拥有Privilege的PowerUser,一类不能拥有Privilege的普通CommonUser,那么他这个模型,单纯以基类继承就很难扩展以描述这种情形了。
要解除这样的限制,最自然的方案就是通过接口。我们可以定义一个IPrivilegeOwner接口和一个BaseUser基类,让PowerUser和CommonUser都继承BaseUser,而PowerUser和UserGroup则实现IPrivilegeOwner。
我们可以发现,当引入接口这样的共享字段契约的概念,我们的模型就能不用受基类继承(大多数系统只支持单根继承)的限制,从而定义得更加灵活,更优雅。
ORM中的继承关系映射全解
0
相关文章
- .NET开发百般武艺:不容小觑的武器库皮丽华 · 2012-04-05
- ORM Profiler提高数据库访问 支持.NET皮丽华 · 2011-10-19
- 理解Oracle Resource Manager晓熊 · 2010-04-09
- Linux的mmap文件内存映射机制周荣茂 · 2010-03-26
- 步步学LINQ to SQL:为实体类添加关系胡铭娅 · 2010-01-06
- 连贯NHibernate1.0 RC版发布胡铭娅 · 2009-08-24
- 微软和开源结合的智慧:NHibernate Linq 1.0 RTM发布胡铭娅 · 2009-07-28
- UbuntuLinux7.10系统下改变域名映射周荣茂 · 2008-05-07
- ASP.NET 2.0新特性之 URL映射nancy · 2007-12-27
- 在ASP.NET 2.0中开发通配符映射应用程序的一些问题nancy · 2007-12-26