组合复用原则
来源:互联网 发布:淘宝订单管理系统介绍 编辑:程序博客网 时间:2024/05/17 16:02
转载地址 http://blog.csdn.net/zhonghuan1992/article/details/38357425
组合复用原则定义:
在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,新的对象通过向这些对象的委派达到复用已有功能的目的
另外一种说法是:尽量使用(对象)组合,而非继承
那么组合和继承各自有什么特点,优缺点,为什么要有这样的优先呢!先来比较一下组合和继承。
组合 VS. 继承
组合复用的优点和缺点
组合
优点:
1容器类仅能通过被包含对象的接口来对其进行访问。
2“黑盒”复用,因为被包含对象的内部细节对外是不可见。
3 封装性好。
4 通过获取指向其它的具有相同类型的对象引用,可以在运行期间动态地定义(对象的)组合。
缺点:
1 导致系统中的对象过多。
2 为了能将多个不同的对象作为组合块(compositionblock)来使用,必须仔细地对接口进行定义。
继承
(类)继承是一种通过扩展一个已有对象的实现,从而获得新功能的复用方法。泛化类(超类)可以显式地捕获那些公共的属性和方法。特殊类(子类)则通过附加属性和方法来进行实现的扩展。
继承的优点和缺点
优点:
1 容易进行新的实现,因为其大多数可继承而来。
2 易于修改或扩展那些被复用的实现。
缺点:
1 破坏了封装性,因为这会将父类的实现细节暴露给子类。
2 “白盒”复用,因为父类的内部细节对于子类而言通常是可见的。
3 当父类的实现更改时,子类也不得不会随之更改。
4 从父类继承来的实现将不能在运行期间进行改变。
要正确使用继承,必须透彻的理解里氏代换原则和Coad法则。里氏代换原则前面学习过,Coad法则由Peter Coad提出,总结了一些什么时候使用继承作为复用工具的条件。只有当以下的Coad条件全部被满足时,才应当使用继承关系:
1 子类是超类的一个特殊种类,而不是超类的一个角色,也就是区分“Has-A”和“Is-A”。只有“Is-A”关系才符合继承关系,“Has-A”关系应当用组合来描述。
2 永远不会出现需要将子类换成另外一个类的子类的情况。如果不能肯定将来是否会变成另外一个子类的话,就不要使用继承。
3 子类具有扩展超类的责任,而不是具有置换调(override)或注销掉(Nullify)超类的责任。如果一个子类需要大量的置换掉超类的行为,那么这个类就不应该是这个超类的子类。
4 只有在分类学角度上有意义时,才可以使用继承。不要从工具类继承。
很多情况下,选择继承关系描述两个类之间的关系,是因为对继承关系的理解不够造成的。下面讨论 Is-A 和 Has-A 的区别。
Is-A 和 Has-A 区别:
Is-A顾名思义,就是“是一个”,意思是一个类是另一个类的一种;Has-A是“有一个”,意思是一个类是另一个类的一部分。
错误的使用继承而不是使用组合,就是把“Has-A”当做“Is-A”。
考虑一下这样的情况。我们每个人都有一个身份,比如我是老师,你是学生,他是运动员。所以,加入要为这样的情况设计我们的类图。可能会是下面的情况。
对应代码如下:
- class Person
- {
- public Person()
- {
- }
- }
- class Teacher extends Person
- {
- public Teacher()
- {
- System.out.println("Iam a teacher.");
- }
- }
- class Student extends Person
- {
- public Student()
- {
- System.out.println("Iam a student.");
- }
- }
- class Athlete extends Person
- {
- public Athlete()
- {
- System.out.println("Iam a athlete");
- }
- }
但是这样的设计,会有问题。我们可以想想,每个人在现实生活中不单单只有一个身份,可能会有很多身份,比如我可以是一个学生,也可以是一名运动员,这并不是一个矛盾的事情。但是上面的设计,忽略了这个因素。导致每个人只有一种身份,这显然是不合理的。
所以,我们重新设计。请看下面的设计,遵循了组合复用原则。
代码如下:
- class Person
- {
- private Role role;
- public Person()
- {
- }
- public void setRole(Role role)
- {
- this.role = role;
- }
- public Role getRole()
- {
- return role;
- }
- }
- interface Role
- {
- }
- class Teacher implements Role
- {
- public Teacher()
- {
- System.out.println("Iam a teacher.");
- }
- }
- class Student implements Role
- {
- public Student()
- {
- System.out.println("Iam a student.");
- }
- }
- class Athlete implements Role
- {
- public Athlete()
- {
- System.out.println("Iam a athlete");
- }
- }
由原来的聚合关系变为现在的组合关系。一个人现在可以有多重角色,在不同的情况下,我们可以给人物设置不同的角色。
- 组合复用原则
- 组合复用原则
- 设计原则:组合复用原则
- 设计原则(三)组合复用原则
- 设计模式---->组合/聚合复用原则
- GoF之组合/聚合复用原则
- 组合/聚合复用原则(CARP)
- 组合/聚合复用原则(Composition/Aggregation Principle)
- 设计模式——组合/聚合复用原则
- 组合/聚合复用原则(Composition/Aggregation Principle)
- java与模式--接口隔离原则,组合聚合复用,迪米特法则,单一职责原则
- 组合/聚合复用原则详解--七大面向对象设计原则(7)
- 组合/聚合复用原则详解--七大面向对象设计原则
- [设计模式]面向对象设计原则之合成/组合复用原则
- 设计模式原则—组合重用原则
- mysql建立组合索引原则
- 设计模式- 合成/组合原则
- 合成复用原则
- 做最真实的自己,做好seo。你懂的
- javascript正则校验电话号码
- BZOJ1583 USACO 2009 Mar Gold 1.Moon Mooing Solution
- Linux守护进程(init.d和xinetd)
- 关于Provision.apk
- 组合复用原则
- Spring security深入杂谈
- POJ 2182 Lost Cows
- 关于Android RenderScript 的详细说明和一些实用文档
- CAS单点登录配置
- Linux下进程信息的深入分析
- Fragment 没有重新加载导致异常
- 关于SVN rollback
- eclipse或者myeclipse版本问题? java.lang.UnsupportedClassVersionError: Bad version number in .class file