Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 为什么要使用构图?_Design Patterns - Fatal编程技术网

Design patterns 为什么要使用构图?

Design patterns 为什么要使用构图?,design-patterns,Design Patterns,我一直在寻找一个答案,关于一个简单的组合代码示例。我知道组合和继承的区别,但我无法用代码来理解 任何基于比较的例子(使用这两种方法)关于我为什么应该使用组合都会非常有用 提前感谢基本区别在于继承在编译时修复类层次结构,而组合允许在运行时决定组合的类关系 对于继承,它使用继承层次结构修复的代码。例如,如果我们从Shape类继承Circle类,Shape固定为Circle类的基类 假设,我们进一步将形状分类为2DShape,和3DShape。现在有了继承,Circle类不可能从2DShape继承 有

我一直在寻找一个答案,关于一个简单的组合代码示例。我知道组合和继承的区别,但我无法用代码来理解

任何基于比较的例子(使用这两种方法)关于我为什么应该使用组合都会非常有用


提前感谢

基本区别在于继承在编译时修复类层次结构,而组合允许在运行时决定组合的类关系

对于继承,它使用继承层次结构修复的代码。例如,如果我们从
Shape
类继承
Circle
类,
Shape
固定为
Circle
类的基类

假设,我们进一步将形状分类为
2DShape
,和
3DShape
。现在有了继承,
Circle
类不可能从
2DShape
继承


有了构图,这是可能的。因此,您可以在运行时将组合类更改为组合类的任何派生类型。

您可能需要选中

支持组合而不是继承是一个设计原则 为设计提供了更高的灵活性,提供了业务领域类 从长远来看,这是一个更稳定的业务领域换句话说, HAS-A可能比IS-A关系更好

检查aleemb的答案,他在其中用代码示例解释了差异

下面是一个有用的例子,解释了为什么选择组合而不是继承

尽管组合和继承都允许重用代码,但继承的缺点之一是它破坏了封装。若子类的操作依赖于超类的行为,它会突然变得脆弱。当超类的行为发生变化时,子类中的功能可能会被破坏,而不会发生任何变化。继承使代码脆弱的一个例子是HashSet中的add()和addAll()方法。假设,如果HashSet的addAll()是通过调用add()方法实现的,并且您编写了HashSet的子类,该子类在插入HashSet之前对内容进行加密。由于只有一个方法add(),它可以将对象插入哈希集中,所以您可以重写这些方法,并通过重写add()调用您的encrypt()方法。这也会自动涵盖addAll(),因为addAll()是使用add()实现的,它看起来非常诱人。如果仔细观察,您会发现此实现非常脆弱,因为它依赖于超类行为。若基类希望提高性能,并在不调用add()方法的情况下实现addAll(),下面的示例将中断

如果您使用组合来支持继承,您将不会面临这个问题,并且您的类将更加健壮,因为您不再依赖于超类行为。相反,您将使用超级类方法来添加部分,并且您将受益于addAll()中的任何改进,如以下示例所示:


我想约书亚·布洛赫说得最好:

我想我已经从下面的链接中得到了答案。基本上,我关心的是更改基类方法的概念如何影响我们是否应该使用继承或组合。我认为如果我们使用继承,并且如果基类函数发生任何更改,那么实际调用的客户端代码将受到影响。但是如果我们使用组合,更改基类函数将需要我们更改使用它的类。客户端代码将保持不变。另一点是,只有在需要使用基类的全部功能时,才应该使用继承。我将再次重申,我重新开始这篇文章的主要关注点是与基类功能的改变有关的。你们上面发布的所有答案都非常有用。但不知何故,我无法标出所有答案。还是要感谢各位的回复,他们真的很有帮助。还有一件事,我希望你们能看看我的回复,在我提出上述问题之后,让我知道我的理解是否正确。
public class EncryptedHashSet extends HashSet{
.....

public boolean add(Object o) {
   return super.add(encrypt(o));
}

}
public class EncryptedHashSet implements Set{
private HashSet container;

public boolean add(Object o) {
   return container.add(encrypt(o));
}

public boolean addAll(Collection c) {
   return conatainer.add(encrypt(c));
}

.......
}