对于两个对象 Foo
和 Bar
,可以定义它们之间的关系:
关联 - 我与一个对象有关系。Foo
使用 Bar
。
public class Foo {
private Bar bar;
};
NB:请参见Fowler的定义 - 关键在于Bar
与Foo
存在语义关联,而不仅仅是依赖项(如int
或string
)。
组合 - 我拥有一个对象并且我对其生命周期负责。当Foo
终止时,Bar
也会随之终止。
public class Foo {
private Bar bar = new Bar();
}
聚合 - 我有一个从别人那里借来的对象。当 Foo
销毁时,Bar
可能会继续存在。
public class Foo {
private Bar bar;
Foo(Bar bar) {
this.bar = bar;
}
}
Bar
对象可能会继续存在。 - Ajay我知道这个问题被标记为 C#,但概念是非常通用的,像这样的问题会重定向到这里。因此,我将在这里提供我的观点(从 Java 角度有些偏见,因为我更熟悉 Java)。
当我们考虑面向对象的特性时,我们总是想到对象、类(对象蓝图)以及它们之间的关系。对象通过方法相互关联和交互。换句话说,一个类的对象可以使用另一个类的对象提供的服务/方法。这种关系称为关联。
聚合和组合是关联的子集,这意味着它们是关联的特定情况。
感到困惑了吗?
组合示例:考虑汽车和仅适用于该汽车的引擎的示例(这意味着它不能用于任何其他汽车)。汽车类与特定引擎类之间的这种关系称为组合。汽车类的对象不能没有特定引擎类的对象存在,而特定引擎类的对象没有汽车类毫无意义。简单来说,汽车类完全“拥有”特定引擎类。
聚合示例: 现在考虑类Car和类Wheel。Car需要一个Wheel对象才能正常运行。意思是Car对象拥有Wheel对象,但我们不能说Wheel对象在没有Car对象的情况下没有意义。它同样可以在Bike、Truck或不同的Cars对象中使用。
总结一下 -
总之,关联是一个非常通用的术语,用于表示一个类使用另一个类提供的功能。如果一个父类对象拥有另一个子类对象,并且该子类对象在没有父类对象的情况下没有实际意义,则我们称其为组合。如果它可以,那么就被称为聚合。
更多详情请点击此处。 我是http://opensourceforgeeks.blogspot.in的作者,并已在上面添加了链接以获取更多上下文信息。
协会是对象之间关系的概括性概念。
组合(混合)是将简单对象或数据类型封装成一个单一单元的方式。组合是许多基本数据结构的关键构建块。
聚合(将多个事物形成一个集群)与普通的组合不同,它不意味着所有权。在组合中,当拥有对象被销毁时,包含的对象也会被销毁。而在聚合中,这并不一定成立。
记住区别的技巧:
背景 | 聚合 | 组合 |
---|---|---|
生命周期 | 对象有自己的生命周期,没有所有者 | 由整体或父对象控制 |
范围 | 父对象和子对象是独立的 | 父对象也意味着其子对象的消亡 |
关系 | 拥有 | 部分 |
强度 | 弱关系 | 强关系 |
现实生活例子 | 汽车和驾驶员 | 汽车和车轮 |
现在让我们观察下面的图片
关联/聚合/组合(紧耦合):在类之间使用实线和关联箭头。这表示类之间的一般关系,一个类的变化可以直接影响另一个类。您还可以使用关联端多重性来表示关系的性质和基数。
依赖/接口或抽象类(松耦合):您可以使用虚线和箭头,从一个类指向另一个类。这表示一个类以某种方式依赖于另一个类。如果供应类的变化直接影响客户类,则依赖关系可以紧密。
类比:
聚合:图像的集合在单个位置。
例如,一所大学拥有各种部门,每个部门都有一些教授。如果大学关闭,这些部门将不再存在,但是这些部门中的教授将继续存在。因此,大学可以被看作是部门的组合,而部门则具有教授的聚合。此外,一个教授可以在多个部门工作,但一个部门不能属于多个大学。public class EnrollmentService {
public void enroll(Student s, Course c){}
}
public class Order {
private Customer customer
}
public class PlayList {
private List<Song> songs;
}
或者
public class Computer {
private Monitor monitor;
}
public class Apartment{
private Room bedroom;
public Apartment() {
bedroom = new Room();
}
}
以下是从Robert Martin在comp.object上的一篇文章中获得的内容:
关联表示一个实例向另一个实例发送消息的能力。通常使用指针或引用实例变量来实现,但也可以通过方法参数或创建本地变量来实现。
//[Example:]
//|A|----------->|B|
class A
{
private:
B* itsB;
};
聚合(Aggregation)[...] 是典型的整体/部分关系。这与关联(association)完全相同,唯一的例外是实例不能具有循环聚合关系(即部分不能包含其整体)。
//[Example:]
//|Node|<>-------->|Node|
class Node
{
private:
vector<Node*> itsNodes;
};
这是聚合的意思,这意味着 Node 的实例不能形成循环。因此,这是 Node 的树而不是图。//[Example:]
//|Car|<#>-------->|Carburetor|
class Car
{
public:
virtual ~Car() {delete itsCarb;}
private:
Carburetor* itsCarb
};
正如其他人所说,关联是对象之间的关系,而聚合和组合是关联的类型。
从实现的角度来看,聚合是通过拥有一个引用类成员来实现的。例如,如果类A聚合了类B的一个对象,你会得到类似下面这样的代码(在C++中):
class A {
B & element;
// or B * element;
};
聚合的语义是,当一个对象 A 被销毁时,它所存储的 B 对象仍将存在。使用组合时,你拥有更强的关系,通常通过按值存储成员实现:
聚合的语义是,当一个对象 A 被销毁时,它所存储的 B 对象仍将存在。使用组合时,你拥有更强的关系,通常通过按值存储成员实现:
class A {
B element;
};
在这里,当A对象被销毁时,它包含的B对象也将被销毁。实现这一点最简单的方法是通过按值存储成员,但您也可以使用一些智能指针,或在析构函数中删除成员:
class A {
std::auto_ptr<B> element;
};
class A {
B * element;
~A() {
delete B;
}
};
重要的是,在组合关系中,容器对象拥有内含对象,而在聚合关系中,它引用它。
在C++社区中,术语“聚合”被用来表示一个类定义了一个属性,用于引用另一个独立类的对象(例如参见[1]),这是UML类图中“关联”的意义。术语“组合”用于定义为其对象定义组件对象的类,因此在复合对象销毁时,这些组件对象也将被销毁。
在UML类图中,"聚合"和"组合"都被定义为表示整体部分关系的特殊情况的关联。在它们的定义中,“聚合”和“组合”的区别基于一个事实,即它是否允许在两个或多个整体之间共享一部分。他们将“组合”定义为具有不可共享(排他)部分的关系,而“聚合”可以共享它们的部分。另外,他们说了类似以下的话:很多情况下,但并非所有情况,组合与其部分之间存在生命周期依赖性,使得部分不能在没有整体的情况下存在。
final class Car {
private final Engine engine;
Car(EngineSpecs specs) {
engine = new Engine(specs);
}
void move() {
engine.work();
}
}
关联(Association)
关联表示两个类之间的关系。它可以是单向的(单方向)或双向的(双方向)
例如:
客户下订单
A与B结婚
B与A结婚
聚合(Aggregation)
聚合是一种关联,但具有特定的特点。聚合是一个较大的“整体”类包含一个或多个较小的“部分”类之间的关系。相反,较小的“部分”类是“整体”较大类的一部分。
例如:
俱乐部有会员
一个俱乐部(“整体”)由几个会员(“部分”)组成。会员可以在俱乐部外生活。如果俱乐部(“整体”)消失了,会员(“部分”)不会随之消失。因为会员可以属于多个俱乐部(“整体”)。
组合(Composition)
这是一种更强的聚合形式。“整体”负责创建或销毁其“部分”
例如:
学校有系
在这种情况下,如果学校(“整体”)消失了,系(“部分”)也将随之消失。 因为每个部分只能属于一个“整体”。
class Club(){ _member = new Member }
还是将其作为引用传递 class Club(){ addMember(Member member) { this._member = member } }
? - Rollyclass Person() { private hand = new Hand }
。Sleep聚合Person:class Person() { private sleep = new Sleep }
。在Sleep中使用关键字“new”是有效的吗?还是应该将其作为引用传递,因为它是聚合?class Person() { private Sleep _sleep; public addSleep(Sleep sleep) { this._sleep = sleep} }
。 - Rolly关联、聚合、组合
关联
,聚合
和组合
都涉及到具有的关系。
聚合
和组合
是关联
的子集,更准确地描述了对象之间的关系。
聚合
- 独立的关系。一个对象可以通过构造函数、方法、setter等传递和保存在类内部。
组合
- 依赖的关系。一个对象由拥有它的对象创建。
*关联是替代子类型的一种选择