partial class:扩展功能新思路

时间:2022-06-20 05:31:39

发表时间:2007-07-10 发表人:陈亮亮

陈亮亮的Blog

开闭原则:“对修改封闭,对扩展开放”。在面向对象的系统中,可以通过类的继承实现扩展。在.net中,partial class提供了扩展类的新思路。

开闭原则

开闭原则是面向对象系统中的一个重要的法则。它可以增强代码的稳定性,分离关注点,提高扩展性。

增强代码稳定性:基类的代码一般情况下不允许修改,如果需要对系统功能进行扩充,可以扩展子类,或实现一个标准接口的模块插入系统。对现有的代码不需要改动。

分离关注点:知道现有的系统功能是什么样就可以,不需要了解系统的内部结构。扩展功能时,只需关注新功能的业务逻辑。

提高扩展性:前面两点说的是“闭”,怎样才能做到“开”就需要系统框架或者语言的支持。比如说“派生”这种开放方式就是由面向对象的语言所支持的,“插件”这种开放方式就是由系统框架支持的。

ORM中的partial class

这里分析一个ORM的例子。

系统中有一个Cat类,属性ID、Age、Weight都需要存储到数据库中,一个信息系统中常见需求。通过读取数据库的结构,可以用工具生成Cat类的代码,并且ORM框架支持了从数据库信息生成Cat对象。

现在的Cat什么动作都没有,客户说,我们需要一个Miaow()的函数。这时就需要对ORM生成的Cat类进行扩展了。

可以肯定的一点是,我们不能修改自动生成的代码,因为这会牵涉到数据库结构与代码同步的问题。解决这个需求有两种方法:继承方式扩展;partial class扩展。

继承方式扩展

工具自动生成一个CatBase类,这个类只有属性,嵌入到ORM框架中。既然需要扩展功能,很容易想到对这个基类继承,于是有了Cat类。Cat类如愿以偿地有了Miaow()函数。

以前系统中用的是CatBase的实例,现在创建CatBase实例的地方需要改为创建Cat的实例。这个问题让ORM框架解决吧。

客户的需求实现了,我们自己的代码生成也没有遭到破坏,任务完成。

partial class扩展

partial class简单地说,就是可以将一个类的代码写到两个或多个代码文件中。编译器在编译的过程中将这几个文件组合起来一起编译。

工具生成的Cat类仍然不变。既然需要增加函数,那么在新建一个代码文件,将Miaow()函数写出来就可以。需要做的仅仅是将类的声明由class改为partial class。

对比分析

两种思路都可以实现需求。孰优孰劣需要仔细分析一下。

实例创建

这两种思路中差别最大的就是实例创建过程。对于继承方式的情况来说,需要采用工厂方法来创建对象。

ClientBase由程序框架提供,具体的MyClient类才依赖于我们的派生类Cat。

而partial class的方式相比之下就要简单得多,因为对于系统来说只存在着Cat类。所以对象创建也是唯一确定的。

系统复杂度

系统的复杂度有很多种衡量方式,类的多少也是其中的一个指标。通常来讲,类的数量越多,系统越复杂。在“简单设计”的原则下,尽可能保证类的数量最少是一个很重要的思路。我曾经在项目中遇到过一个模块,当前后采用不同的模式实现的时候,类数量的差距竟然可以达到两倍多。

而在现在这个场景下,使用partial class方式下只存在一个类,而继承方式有两个类。当这样的实体类很多的时候,系统复杂度就成了一个不可忽视的要素了。

继承逻辑

从逻辑上讲,Cat并不需要一个基类CatBase,这样做仅仅是因为在代码构建过程中的一个限制。

面向对象系统中的类可以分为两种,一种是现实世界中切实存在的概念;另外一个是现实世界中不存在但是由于语言、框架、运行环境等软件技术的限制而不得不加入到系统的。

其中CatBase类就是属于第二种。随着软件编译技术、程序框架的不断进步,这种类也会越来越少。

维护性、可读性

两种方式下都会存在两个代码文件,从需要维护的文档数来看,成本并无区别。但使用partial class方式会出现两个Cat文件:一个由工具自动生成,另一个由我们手工编写。不理解这种思想的人会觉得特别费解。

整体上说,使用partial class更加优雅一些。

“继承”的这种方式比较符合传统的思维习惯,而partial class到底是否OO,这点确实不好说。不过在软件构建上,我是一个实用主义者,哪种方式好用就用哪一种。

在ORM的场景中,partial class更加好一些,但有的时候,两个类之间确实就存在继承关系,那么就必须用到继承了。虽然绝大多数情况下,都需要继承方式,但是既然有了partial class技术,我们在做设计时也需要考虑这个思路。

可以使用partial class的场景很多,最常见的就是VS2005中的界面设计,在VS2005中,Form、DataSet都使用了partial class方式,原理和这个一样。但是要将这个原理推广到“业务实体”中,可能在理解上需要有所突破。

使用partial class确实会带来可读性的损失,尤其是一个类分布在多个文件中时,所以文件的命名最好是有一个规范来保证。

编程语言都在不断地发展,不断地融合。在动态语言中,很早就有了类似的思路。虽说语言只是工具,但每种工具都有自己的独特之处。工具的功能越强大,我们设计人员的思路应该越宽广。

陈亮亮的Blog介绍∷

中国传统的智慧在于“道”,现在的软件技术为“术”。

谁说中国的传统文化就是落后的代名词。我相信经过我们这一代的努力,中国的传统将会在新兴的软件行业大放异彩。

我的Blog致力于将传统与现代相结合,同时赋予软件和中国文化一个全新的视角。

欢迎大家来我的Blog做客。

个人信息∷

陈亮亮,毕业于北京大学微电子学系,研究业务平台,插件技术等。目前正学习架构设计与软件开发过程管理。兴趣驳杂,易经、中医、软件、管理都略有涉猎。

陈亮亮的文章分类∷

插件系统(RSS)

读易(RSS)

管理之道(RSS)

技术之旅(RSS)

漫漫人生(RSS)

陈亮亮的文章∷

Command模式与动态语言

业务平台在系统中的位置

系统组装策略分析

上一篇:管理最有价值的资产 下一篇:ITIL魔法学院