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

技术面向对象设计原则之合成复用原则 面向对象设计原则之合成复用原则转载来自: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)

相关推荐

  • 软件设计-模板方法模式

    技术软件设计-模板方法模式 软件设计-模板方法模式数据库连接对数据库的操作一般包括连接、打开、使用、关闭等步骤,在数据库操作模板类中我们定义了connDB()、openDB()、useDB()、clos

    礼包 2021年12月14日
  • 746. 使用最小花费爬楼梯

    技术746. 使用最小花费爬楼梯 746. 使用最小花费爬楼梯数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值cost[i](下标从 0 开始)。
    每当你爬上一个阶梯你都要花费对应

    礼包 2021年10月26日
  • Sqlview动态发布地图图层的方法是什么

    技术Sqlview动态发布地图图层的方法是什么Sqlview动态发布地图图层的方法是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1.SQL Views

    攻略 2021年11月30日
  • Windows中能够提取出图片边缘特征的网络是什么

    技术Windows中能够提取出图片边缘特征的网络是什么这篇文章主要介绍“Windows中能够提取出图片边缘特征的网络是什么”,在日常操作中,相信很多人在Windows中能够提取出图片边缘特征的网络是什么问题上存在疑惑,小

    攻略 2021年11月9日
  • sparkmllib运行原理(spark中mlli应用场景)

    技术Spark中MLlib和ML库的区别是什么这篇文章给大家介绍Spark中MLlib和ML库的区别是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。机器学习库(MLlib)MLlib是Spark

    攻略 2021年12月17日
  • Python如何爬取北京市所有电子眼名

    技术Python如何爬取北京市所有电子眼名Python如何爬取北京市所有电子眼名,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。前言今天给大家分享一篇非常

    攻略 2021年10月26日