关联、聚合和组合之间的区别是什么? 请从实施的角度加以说明。
当前回答
摘自:Remo H. Jansen的《Beginning React: Learning TypeScript 2》。x -第二版”:
We call association those relationships whose objects have an independent life cycle where there is no ownership of the objects. Let's take a look at an example of a teacher and a student. Multiple students can be associated with a single teacher, and a single student can be associated with multiple teachers, but both have independent life cycles (both can create and delete independently). So, when a teacher leaves the school, we don't need to delete any students, and when a student leaves the school, we don't need to delete any teachers.
我们称这些关系为聚合,其对象具有独立的生命周期,但存在所有权,并且子对象不能属于另一个父对象。让我们以手机和电池为例。单个电池可以属于一个手机,但如果手机停止工作,我们从数据库中删除它,手机电池将不会被删除,因为它可能仍在工作。因此,在聚合中,虽然有所有权,但对象有它们的生命周期
我们使用术语组合来指代对象没有独立生命周期的关系,如果父对象被删除,所有子对象也将被删除。让我们以问题和答案之间的关系为例。一个问题可以有多个答案,答案不能属于多个问题。如果我们删除问题,答案将自动删除。
其他回答
依赖性(引用) 这意味着两个物体之间没有概念上的联系。例如:enroll service对象引用Student & Course对象(作为方法参数或返回类型)
public class EnrollmentService {
public void enroll(Student s, Course c){}
}
协会(有) 这意味着对象之间几乎总是有一个链接(它们是相关联的)。 Order对象有一个Customer对象
public class Order {
private Customer customer
}
聚合(has-a + whole-part) 两个对象之间存在整体-部分关系的一种特殊联想。但他们可能没有彼此。
public class PlayList {
private List<Song> songs;
}
OR
public class Computer {
private Monitor monitor;
}
注意:最棘手的部分是区分聚合和普通关联。老实说,我认为这有不同的解释。
组成(has-a +整体部分+所有权) 一种特殊的聚合。公寓是由一些房间组成的。没有公寓,就没有房间。删除一个公寓时,所有关联的房间也会被删除。
public class Apartment{
private Room bedroom;
public Apartment() {
bedroom = new Room();
}
}
联想是关系的广义概念。它包括组合和聚合。
组合(混合)是一种将简单对象或数据类型包装成单个单元的方法。组合是许多基本数据结构的关键构建块
聚合(将许多事物形成一个集群)不同于普通的组合,因为它不意味着所有权。在组合中,当拥有的对象被销毁时,包含的对象也被销毁。总的来说,这并不一定正确。
记住区别的技巧:
“有一个”:聚合 “局部”:comPOsitoin “是一个”:继承
context | Aggregation | Composition |
---|---|---|
Life time | objects have their own lifetime and there is no owner | controlled by whole or parent that owns it |
Scope | parent objects and child objects are independent | parent object also means the death of its children. |
Relationship | Has-a | Part-of |
Strength | weak relationship | strong relationship. |
Real-life example | Car and Driver | Car and wheels |
现在让我们观察下面的图像
类比:
合成:下图是图像合成,即使用单独的图像合成一张图像。
聚合:图像在单一位置的集合
例如,A大学有多个系,每个系都有一些教授。如果大学关闭,这些部门将不复存在,但这些部门的教授将继续存在。因此,一所大学可以被看作是一个系的组成部分,而系则是教授的集合。此外,教授可以在一个以上的部门工作,但一个部门不能属于一所以上的大学。
协会
关联表示两个类之间的关系。它可以是单向的(单向)或双向的(双向)
例如:
单向
客户下单
双向
A和B结婚了 B和A结婚了
聚合
聚合是一种关联。但是有特定的特征。聚合是一个较大的“整体”类包含一个或多个较小的“部分”类之间的关系。相反,一个较小的“部分”类是“整个”较大类的一部分。
例如:
俱乐部有会员
一个俱乐部(“整体”)是由几个俱乐部成员(“部分”)组成的。会员可以在俱乐部外生活。如果俱乐部(“整体”)死亡,成员(“部分”)不会随之死亡。因为会员可以属于多个俱乐部(“整体”)。
作文
这是一种更强的聚合形式。“整体”对其“部分”的创造或破坏负责
例如:
学校有院系
在这种情况下,学校(“整体”)将消亡,部门(“部分”)将随之消亡。 因为每个部分只能属于一个“整体”。
我想说明如何在Rails中实现这三个术语。ActiveRecord将两个模型之间的任何类型的关系称为关联。在阅读文档或文章时,人们不会经常发现术语组合和聚合与ActiveRecord相关。通过向类的主体中添加一个关联类宏来创建关联。其中一些宏是belongs_to, has_one, has_many等。
If we want to set up a composition or aggregation, we need to add belongs_to to the owned model (also called child) and has_one or has_many to the owning model (also called parent). Wether we set up composition or aggregation depends on the options we pass to the belongs_to call in the child model. Prior to Rails 5, setting up belongs_to without any options created an aggregation, the child could exist without a parent. If we wanted a composition, we needed to explicitly declare this by adding the option required: true:
class Room < ActiveRecord::Base
belongs_to :house, required: true
end
在Rails 5中,这一点被改变了。现在,声明belongs_to关联在默认情况下创建了一个组合,子元素不能没有父元素而存在。所以上面的例子可以重写为:
class Room < ApplicationRecord
belongs_to :house
end
如果我们想要允许子对象在没有父对象的情况下存在,我们需要通过选项optional显式地声明这一点
class Product < ApplicationRecord
belongs_to :category, optional: true
end
It's important to understand why we should even bother with using more than once relationship line. The most obvious reason is to describe parent-child relationship between classes (when parent deleted all its child’s are deleted as a result), but more impotently, we want to distinguish between simple association and composition in order to place implicit restrictions on the visibility and propagation of changes to the related classes, a matter which plays an important role in understanding and reducing system complexity.
协会
描述类之间静态关系的最抽象的方法是使用Association链接,它简单地说明两个或多个类之间存在某种类型的链接或依赖关系。
弱协会
类a可以链接到类b,以显示其方法之一包含类b实例的参数,或返回类b实例。
强大的协会
类a也可以被链接到类b,以显示它持有对类b实例的引用。
聚合(共享关联)
在类a(整体)和类b(部分)之间存在部分关系的情况下,我们可以更具体地使用聚合链接而不是关联链接,强调类b也可以由应用程序中的其他类聚合(因此聚合也称为共享关联)。
需要注意的是,聚合链接并没有以任何方式说明ClassA拥有ClassB,也没有说明两者之间存在父子关系(当父类删除其所有子类时,其结果也将被删除)。事实上,恰恰相反!聚合链接通常用于强调ClassA不是ClassB的独占容器,因为实际上ClassB有另一个容器。
聚合vs .关联 关联链接在任何情况下都可以取代聚合链接,而聚合不能在类之间只有“弱链接”的情况下取代关联,即类a有包含类b参数的方法,但类a不包含对类b实例的引用。
马丁·福勒认为聚合链接根本不应该使用,因为它没有附加价值,而且会扰乱一致性,引用吉姆·拉姆博的话:“把它看作建模安慰剂”。
组合(非共享关联)
我们应该更具体地使用复合链接,在这种情况下,除了类a和类b之间的部分关系之外——两者之间有很强的生命周期依赖关系,这意味着当类a被删除时,ClassB也会被删除
复合链接表明一个类(容器,整体)对其他类(部分)具有独占所有权,这意味着容器对象及其部分构成了父子关系。
与关联和聚合不同,在使用组合关系时,组合类不能作为组合类的返回类型或参数类型出现。因此,对组合类的更改不能传播到系统的其余部分。因此,随着系统的增长,组合的使用限制了复杂性的增长。
测量系统复杂性
System complexity can be measured simply by looking at a UML class diagram and evaluating the association, aggregation, and composition relationship lines. The way to measure complexity is to determine how many classes can be affected by changing a particular class. If class A exposes class B, then any given class that uses class A can theoretically be affected by changes to class B. The sum of the number of potentially affected classes for every class in the system is the total system complexity.
你可以在我的博客上阅读更多: http://aviadezra.blogspot.com/2009/05/uml-association-aggregation-composition.html
推荐文章
- 是什么导致这个ActiveRecord::ReadOnlyRecord错误?
- 在Java中使用“final”修饰符
- Rails:dependent =>:destroy VS:dependent =>:delete_all
- 我怎么知道什么时候创建一个接口?
- 构造函数vs工厂方法
- 在PHP5中创建单例设计模式
- 什么是依赖倒置原则?为什么它很重要?
- 从Java项目生成UML类图
- 为什么在Python方法中需要显式地有“self”参数?
- js:将一个组件包装成另一个组件
- 如何在方法中访问“静态”类变量?
- 为什么c#不提供c++风格的'friend'关键字?
- String, StringBuffer和StringBuilder
- 显示所有Elasticsearch聚合结果/桶,而不仅仅是10个
- 存储库和服务层的区别?