"合成聚合复用原则" (转http://www.cnblogs.com/supertbt/archive/2007/03/07/666319.html)
2010-11-18 09:11
363 查看
走想设计5--"合成聚合复用原则"
合成(Composition)和聚合(Aggregation)都是关联(Association)的特殊种类。聚合表示整体和部分的关系,表示“拥有”;合成则是一种更强的“拥有”,部分和整体的生命周期一样。合成的新的对象完全支配其组成部分,包括它们的创建和湮灭等。一个合成关系的成分对象是不能与另一个合成关系共享的。换句话说,合成是值的聚合(Aggregation by Value),而一般说的聚合是引用的聚合(Aggregation by Reference)。
简短的说,合成-聚合复用原则(CARP)是指,尽量使用合成/聚合,而不是使用继承。
在OOD中,有两种基本的办法可以实现复用,一种是通过合成/聚合,另外一种就是通过继承。通过合成/聚合的好处是:
新对象存取成分对象的唯一方法是通过成分对象的接口。
这种复用是黑箱复用,因为成分对象的内部细节是新对象所看不见的。
这种复用支持包装。
这种复用所需的依赖较少。
每一个新的类可以将焦点集中在一个任务上。
这种复用可以在运行时间内动态进行,新对象可以动态的引用与成分对象类型相同的对象。
作为复用手段可以应用到几乎任何环境中去。
它的缺点就是系统中会有较多的对象需要管理。
通过继承来进行复用的优点是:
新的实现较为容易,因为超类的大部分功能可以通过继承的关系自动进入子类。
修改和扩展继承而来的实现较为容易。
缺点是:
继承复用破坏包装,因为继承将超类的实现细节暴露给子类。由于超类的内部细节常常是对于子类透明的,所以这种复用是透明的复用,又称“白箱”复用。
如果超类发生改变,那么子类的实现也不得不发生改变。
从超类继承而来的实现是静态的,不可能在运行时间内发生改变,没有足够的灵活性。
继承只能在有限的环境中使用。
要正确的选择合成/复用和继承,必须透彻的理解里氏代换原则和Coad法则。里氏代换原则前面学习过,Coad法则由Peter Coad提出,总结了一些什么时候使用继承作为复用工具的条件。只有当以下的Coad条件全部被满足时,才应当使用继承关系:
子类是超类的一个特殊种类,而不是超类的一个角色,也就是区分“Has-A”和“Is-A”。只有“Is-A”关系才符合继承关系,“Has-A”关系应当用聚合来描述。
永远不会出现需要将子类换成另外一个类的子类的情况。如果不能肯定将来是否会变成另外一个子类的话,就不要使用继承。
子类具有扩展超类的责任,而不是具有置换调(override)或注销掉(Nullify)超类的责任。如果一个子类需要大量的置换掉超类的行为,那么这个类就不应该是这个超类的子类。
只有在分类学角度上有意义时,才可以使用继承。不要从工具类继承。
错误的使用继承而不是合成/聚合的一个常见原因是错误的把“Has-A”当成了“Is-A”。“Is-A”代表一个类是另外一个类的一种;“Has-A”代表一个类是另外一个类的一个角色,而不是另外一个类的特殊种类。
我们看一个例子。如果我们把“人”当成一个类,然后把“雇员”,“经理”,“学生”当成是“人”的子类。这个的错误在于把“角色”的等级结构和“人”的等级结构混淆了。“经理”,“雇员”,“学生”是一个人的角色,一个人可以同时拥有上述角色。如果按继承来设计,那么如果一个人是雇员的话,就不可能是经理,也不可能是学生,这显然不合理。正确的设计是有个抽象类“角色”,“人”可以拥有多个“角色”(聚合),“雇员”,“经理”,“学生”是“角色”的子类。
另外一个就是只有两个类满足里氏代换原则的时候,才可能是“Is-A”关系。也就是说,如果两个类是“Has-A”关系,但是设计成了继承,那么肯定违反里氏代换原则。
相关文章推荐
- C++项目中的extern "C" {}(转自:http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html)
- IIS 中 "另一个程序正在使用此文件,进程无法访问!" http://www.cnblogs.com/publicbill/archive/2007/05/29/763844.html
- 对 "闭包-closure" 的一些见解http://wj.cnblogs.com/archive/2006/04/22/381851.html
- [转-来自啊泰]推模式下dataset1下显示的是"...未找到项目..." 问题的解决[补充] [http://www.cnblogs.com/babyt/archive/2005/04/15/138588.html]
- C++中引用(&)(来自http://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html)
- [转-来自啊泰]推模式下dataset1下显示的是"...未找到项目..." 问题的解决 [http://www.cnblogs.com/babyt/archive/2005/04/15/138582.html]
- JPA & Hibernate 注解 (转http://www.cnblogs.com/minideas/archive/2010/12/31/1922672.html)
- 数组里a和&a的区别(转自:http://www.cnblogs.com/auleaf/archive/2011/09/19/2181346.html)
- vs2005下彩色验证码的实现(可自由定义是否加入干扰点、验证码位数等验证码显示效果) <br />转自<a href="http://www.cnblogs.com/zm235/archive/2006/10/02/520233.html" target="_blank">http://www.cnblogs.com/zm235/archive/2006/10/02/520233.html</a>
- Silverlight & Blend动画设计系列三:缩放动画(ScaleTransform) from http://www.cnblogs.com/beniao/archive/2010/03/26/1694157.html
- 转载:字符集和字符编码(Charset & Encoding) http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html
- Silverlight & Blend动画设计系列一:偏移动画(TranslateTransform) from http://www.cnblogs.com/beniao/archive/2010/03/21/1685670.html
- setInterval和setTimeout的使用区别(转自 <a href="http://www.cnblogs.com/sk-net/archive/2008/01/24/1050770.html">http://www.cnblogs.com/sk-net/archive/2008/01/24/1050770.html</a>)
- 一个优秀.NET程序员的技能树(http://www.cnblogs.com/Jax/archive/2007/09/02/879079.html)
- http://www.cnblogs.com/iminto/archive/2010/12/23/1915232.html
- http://www.cnblogs.com/qqloving/archive/2012/02/25/2367813.html
- http://www.cnblogs.com/Matrix54/archive/2012/05/03/2481260.html
- 全球只有4个人通关的游戏!你行吗? 转自:http://www.cnblogs.com/RuiLei/archive/2008/06/07/1215624.html
- Oracle数据库备份与恢复之一:exp/imp(原文http://www.cnblogs.com/sungod/archive/2011/03/13/1983090.html)
- 最优化javascript自定义对象(转自:http://www.cnblogs.com/QiuYun/archive/2007/03/22/684523.html)