nxh*_*oaf 91
根据经验:

class Person {
private Heart heart;
private List<Hand> hands;
}
class City {
private List<Tree> trees;
private List<Car> cars
}
Run Code Online (Sandbox Code Playgroud)
在构图(人物,心脏,手)中,一旦人物被摧毁,"子物体"(心脏,手)将被销毁.
在聚合(城市,树,汽车)中,当城市被摧毁时,"子对象"(树,汽车)将不会被销毁.
底线是,组合强调相互存在,而在聚合中,这个属性不是必需的.
Hex*_*gon 88
聚合和组合之间的区别取决于上下文.
以另一个答案中提到的汽车为例 - 是的,确实汽车尾气可以"独立",因此可能不会与汽车组成 - 但这取决于应用.如果您构建的应用程序实际上必须处理独立的汽车尾气(汽车商店管理应用程序?),那么聚合将是您的选择.但如果这是一个简单的赛车游戏,汽车尾气只能作为汽车的一部分 - 好吧,组成会很好.
国际象棋棋盘?同样的问题.只有在某些应用程序中,没有棋盘就不存在国际象棋棋子.在其他人(如玩具制造商的那些)中,棋子肯定不能组成棋盘.
在尝试将合成/聚合映射到您喜欢的编程语言时,情况变得更糟.在某些语言中,差异可能更容易被注意到("通过引用"与"按价值",当事情很简单时),但在其他语言中可能根本不存在.
还有最后一条忠告?不要在这个问题上浪费太多时间.这不值得.这种区别在实践中几乎没有用(即使你有一个完全清晰的"组合",你可能仍然希望将其作为聚合实现,因为技术原因 - 例如,缓存).
vsi*_*ngh 47
组合和聚合是关联的类型.它们密切相关,在编程方面没有太大的区别.我将尝试通过java代码示例解释这两者之间的区别
聚合:对象存在于另一个之外,在外部创建,因此它作为参数(例如)传递给construtor.例如:人 - 车.汽车是在不同的环境中创造的,然后成为人的财产.
// code example for Aggregation:
// reference existing HttpListener and RequestProcessor
public class WebServer {
private HttpListener listener;
private RequestProcessor processor;
public WebServer(HttpListener listener, RequestProcessor processor) {
this.listener = listener;
this.processor = processor;
}
}
Run Code Online (Sandbox Code Playgroud)
构成:对象只存在,或者只在另一个内部有意义,作为另一个的一部分.例如:人 - 心.你不会创造一颗心,然后将它传递给一个人.
// code example for composition:
// create own HttpListener and RequestProcessor
public class WebServer {
private HttpListener listener;
private RequestProcessor processor;
public WebServer() {
this.listener = new HttpListener(80);
this.processor = new RequestProcessor(“/www/root”);
}
}
Run Code Online (Sandbox Code Playgroud)
这里用一个例子来解释聚合和组合之间的区别
Dav*_*d M 36
组合意味着子对象与父对象共享生命周期.聚合没有.例如,国际象棋棋盘由国际象棋方块组成 - 国际象棋方块在没有棋盘的情况下并不存在.然而,汽车是零件的集合 - 如果汽车排气装置当时不是汽车的一部分,那么它仍然是汽车尾气.
Chr*_*sel 18
我学到的例子是手指.你的手是由手指组成的.它拥有它们.如果手死了,手指就会死亡.你不能"聚合"手指.你不能只是抓住多余的手指,随意地将它们从手上移开.
从设计的角度来看,这里的价值通常与对象的生命周期有关,正如另一张海报所说.假设您有一位客户并且他们有一个帐户.该帐户是客户的"组合"对象(至少在我能想到的大多数情况下).如果您删除了客户,则该帐户没有自己的价值,因此也会被删除.在对象创建方面通常是相反的.由于帐户仅在客户的上下文中具有意义,因此您将创建帐户作为客户创建的一部分(或者,如果您懒惰地执行,则它将成为某个客户交易的一部分).
在设计中考虑哪些对象拥有(组合)其他对象与仅引用(聚合)其他对象的对象是有用的.它可以帮助确定对象创建/清理/更新的责任.
就代码而言,通常很难说.代码中的大部分内容都是对象引用,因此引用的对象是组合(拥有)还是聚合可能并不明显.
Ger*_*ner 14
令人惊讶的是,关于部分 - 整体 - 关联概念聚合和组合之间的区别存在多少混淆.主要问题是普遍的误解(即使是专家软件开发人员和UML的作者之间),构成的概念意味着整体与其各部分之间的生命周期依赖性,使得部分在没有整体的情况下不可能存在.但是这种观点忽略了这样一个事实,即存在与不可共享部分的部分整体关联的情况,其中部分可以与整体的分离分离并在其中存活.
在UML规范文档中,术语"组合"的定义总是暗示不可共享的部分,但尚不清楚"组合"的定义特征是什么,而仅仅是可选特征.即使在新版本(截至2015年),UML 2.5中,在尝试改进术语"组合"的定义之后,它仍然仍然含糊不清,并没有提供任何指导如何模拟与非组合的整体关联可分离的部件,其中部件可以从整体上拆下并经受损坏,而不是部件不能脱离并且与整体一起被破坏的情况.他们说
如果删除了复合对象,则会删除作为对象的所有零件实例.
但与此同时他们也说
在删除复合对象之前,可以从复合对象中删除部件对象,因此不会将其作为复合对象的一部分删除.
这种混淆指向UML定义的不完整性,该定义不考虑组件和组合之间的生命周期依赖性.因此,了解如何通过为" 不可分离的 "组合引入UML构造型来增强UML定义是很重要的,其中组件不能从它们的组合中分离,因此,每当它们的组合被销毁时都必须被销毁.
正如Martin Fowler所解释的那样,表征构图的主要问题是"一个对象只能是一个构图关系的一部分".Geert Bellekens 的优秀博客文章UML Composition vs Aggregation vs Association也解释了这一点.除了组合物的这种定义特征(具有独占或不可共享的部分)之外,组合物还可以在复合物与其组分之间具有生命周期依赖性.实际上,有两种这样的依赖:
Person和之间的组合来举例说明Heart.当一个人的主人已经死亡时,心脏会被摧毁或移植到另一个人身上.Person和Brain.
总之,生命周期依赖性仅适用于特定的组合情况,但一般而言,它们不是一个定义特征.
UML规范声明:"在删除复合实例之前,可以从复合实例中删除部件,因此不会将其作为复合实例的一部分删除." 在Car- Engine组合的例子中,如下图所示,显然情况是在汽车被摧毁之前发动机可以从汽车上拆下,在这种情况下发动机不会被破坏并且可以重新使用.这由组合线的复合面上的零或一个多重性暗示.

复合边的组合物关联结束的多重性是1或0..1,这取决于组件是否具有强制复合(必须连接到复合材料)的事实.如果组件是不可分割的,这意味着它们具有强制性组合.
聚合是与部分 - 整体关系的预期含义相关联的另一种特殊形式,其中整体的各部分可以与其他整体共享.例如,我们可以模型中的类之间的聚集DegreeProgram和Course,如下面的图中,由于过程是一定程度的程序的一部分,并且一个疗程可以在两个或更多的程度的程序之间共享(例如,工程度可以共享一个C具有计算机科学学位的编程课程).

然而,具有可共享部分的聚合的概念并不意味着真的,因此它对实现没有任何影响,因此许多开发人员不喜欢在他们的类图中使用白色菱形,而只是模拟一个简单的关联代替.UML规范说:"共享聚合的精确语义因应用领域和建模者而异".
整个侧面的聚合关联结束的多样性可以是任何数字(*),因为部分可以属于任何数量的整体,或者在任何数量的整体之间共享.
小智 8
在代码术语中,组合通常建议包含对象负责创建组件*的实例,并且包含对象保存对它的唯一长期引用.因此,如果父对象被取消引用并被垃圾收集,那么孩子也将如此.
所以这段代码......
Class Order
private Collection<LineItem> items;
...
void addOrderLine(Item sku, int quantity){
items.add(new LineItem(sku, quantity));
}
}
Run Code Online (Sandbox Code Playgroud)
表明LineItem是Order的一个组件 - LineItems在其包含顺序之外不存在.但Item对象不是按顺序构建的 - 它们是根据需要传递的,并且继续存在,即使商店没有订单.所以它们是关联的,而不是组件.
*nb容器负责实例化组件,但它实际上可能不会调用new ...()本身 - 这是java,通常首先要经过一两个工厂!
| 归档时间: |
|
| 查看次数: |
76691 次 |
| 最近记录: |