面向对象设计原则之合成复用原则

技术面向对象设计原则之合成复用原则 面向对象设计原则之合成复用原则转载来自:https://blog.csdn.net/lovelion/article/details/7563441
合成复用原则又称

面向对象设计原则的组成和重用原则。

转载自:https://blog.csdn.net/lovelion/article/details/7563441

组合原则,也称为组合/聚合重用原则(carp),定义如下:

合成复用原则(Composite Reuse Principle, CRP):尽量使用对象组合,而不是继承来达到复用的目的。

组合的原理是通过关联关系(包括组合关系和聚合关系)将一个新对象中已有的一些对象利用起来,使它们成为新对象的一部分。新对象通过委托现有对象的方法来达到重用功能的目的。简而言之,应该尽可能使用组合/聚合关系(关联关系),少用继承。

在面向对象设计中,有两种方法可以在不同的环境中重用现有的设计和实现,即通过组合/聚合关系或通过继承,但首先要考虑组合/聚合。组合/聚合可以使系统更加灵活,减少类与类之间的耦合,一个类的变化对其他类的影响相对较小。其次,要考虑继承。使用继承时,需要严格遵循Richter替换原则。有效利用继承有助于理解问题,降低复杂性,而滥用继承会增加系统构建和维护的难度,增加系统的复杂性。因此,谨慎使用继承重用是必要的。

通过继承进行重用的主要问题是继承重用会破坏系统的封装,因为继承会将基类的实现细节暴露给子类。由于基类的内部细节通常对子类可见,这种重用也被称为“白盒”重用。如果基类改变了,子类的实现也必须改变。从基类继承的实现是静态的,不能在运行时更改,并且不够灵活。此外,继承只能在有限的环境中使用(例如,没有声明一个类不能被继承)。

发展

对于继承的深刻理解,可以参考《软件架构设计》的作者虞雯写的文章—— 《见山只是山见水只是水——提升对继承的认识》。

因为组合或聚合关系可以将现有对象(也称为成员对象)合并到新对象中,并使其成为新对象的一部分,所以新对象可以调用现有对象的函数,这可以使成员对象的内部实现细节对新对象不可见。所以,这种复用也叫“黑箱”复用。与继承关系相比,其耦合度相对较低,成员对象的变化对新对象影响不大。合成可以在运行时动态完成,新对象可以动态引用与成员对象相同类型的其他对象。

一般来说,如果两个类之间的关系是“Has-A”,就应该用组合或者聚合,如果是“Is-A”,就可以用继承。“Is-A”是一个严格的分类学定义,意思是一个类是另一个类的“一种”;和“有-有”不同,它意味着某个角色有一定的责任。

下面是一个简单的例子来加深对复合复用原理的理解:

在Sunny Software公司早期的CRM系统设计中,考虑到客户数量少,系统使用MySQL作为数据库,需要将CustomerDAO类等与数据库操作相关的类连接到数据库,将连接数据库的方法getConnection()封装在DBUtil类中。由于需要重用DBUtil类的getConnection()方法,设计人员将CustomerDAO作为DBUtil类的子类,初步设计方案结构如图1所示。

图1初步设计方案结构图。

随着客户数量的增加,系统决定升级到Oracle数据库,因此需要添加一个新的OracleDBUtil类来连接Oracle数据库。由于在最初的设计方案中,CustomerDAO和DBUtil之间存在继承关系,所以在改变数据库连接方式时,需要修改CustomerDAO类的源代码,将CustomerDAO做成OracleDBUtil的子类,这样会违反开闭原则。【当然也可以修改DBUtil类的源代码,这样也会违反开闭原则。】

现在利用复合复用的原理进行重构。

按照复合复用的原则,在实现复用时要多关联少继承。因此,在这个例子中,我们可以使用关联复用代替继承复用,重构后的结构如图2所示:

图2改造后的结构图。

在图2中,CustomerDAO和DBUtil之间的关系从继承变为关联,DBUtil对象通过依赖注入注入到CustomerDAO中,或者通过构造注入,或者通过Setter注入。如果需要扩展DBUtil的功能,可以通过它的子类来实现,比如通过子类OracleDBUtil连接Oracle数据库。由于CustomerDAO是为DBUtil编程的,根据Richter替换原理,DBUtil子类的对象可以覆盖DBUtil对象,子类扩展的方法只能通过将子类注入CustomerDAO来使用。比如通过将OracleDBUtil对象注入CustomerDAO,可以实现Oracle数据库连接,不需要修改原代码,可以灵活添加新的数据库连接方式。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/70037.html

(0)

相关推荐

  • 如何实现web微前端沙箱

    技术如何实现web微前端沙箱这篇文章主要讲解了“如何实现web微前端沙箱”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何实现web微前端沙箱”吧!背景应用沙箱可能是微前

    攻略 2021年11月15日
  • 什么叫奇数什么叫偶数,什么叫做偶数

    技术什么叫奇数什么叫偶数,什么叫做偶数定义什么叫奇数什么叫偶数:整数中,能够被2整除的数,叫做偶数. 若不能,它就是奇数特别提示:偶数包括正偶数、负偶数和0.
    所有整数不是奇数(又称单数),就是偶数(又称双数).若某数是

    生活 2021年10月23日
  • 电子邮箱怎么注册,应用开发者注册电子邮箱怎么

    技术电子邮箱怎么注册,应用开发者注册电子邮箱怎么1电子邮箱怎么注册、其实itunes store的账号很好注册的,首先你要你要有个自己没有注册过apple ID的电子邮箱地址,用于注册你的APPLE ID,QQ邮箱也可以

    生活 2021年10月28日
  • SQL server服务显示远程过程调用失败的解决方法

    技术SQL server服务显示远程过程调用失败的解决方法本篇文章给大家分享的是有关SQL server服务显示远程过程调用失败的解决方法,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不

    攻略 2021年11月30日
  • 如何使用phoenix操作hbase数据)

    技术如何使用phoenix操作hbase数据)这篇文章将为大家详细讲解有关如何使用phoenix操作hbase数据),小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1.下载安装phoen

    攻略 2021年12月9日
  • python编程实现用for计算n的阶乘(python如何编写阶乘)

    技术Python如何实现阶乘之和这篇文章给大家分享的是有关Python如何实现阶乘之和的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码实现Sum=0
    factorial=1
    num = in

    攻略 2021年12月14日