关联、聚合和组合之间的区别是什么? 请从实施的角度加以说明。


当前回答

https://www.linkedin.com/pulse/types-relationships-object-oriented-programming-oop-sarah-el-dawody/

Composition:是一种“part-of”关系。

例如,“发动机是汽车的一部分”,“心脏是身体的一部分”。

关联:是“has-a”类型的关系

例如,假设我们有两个类,那么这两个类被称为“has-a”关系,如果这两个实体为了某些工作而共享彼此的对象,同时它们可以不依赖彼此而存在,或者它们都有自己的生命期。

上面的示例显示了一种关联关系,因为Employee类和Manager类都使用彼此的对象,并且都有各自独立的生命周期。

聚合:是基于“has-a”关系,是一种特殊的关联形式

例如,“学生”和“地址”。每个学生必须有一个地址,所以学生类和地址类之间的关系将是“Has-A”类型的关系,反之亦然。

其他回答

对于Foo和Bar这两个对象,可以定义关系

关联——我与一个对象有一种关系。Foo使用Bar

public class Foo {         
    private Bar bar;
};

注意:请参阅Fowler的定义-关键是Bar在语义上与Foo相关,而不仅仅是一个依赖项(如int或字符串)。

组合——我拥有一个对象,我对它的生命周期负责。当Foo死了,Bar也死了

public class Foo {
    private Bar bar = new Bar(); 
}

聚合——我有一个从别人那里借来的对象。当Foo死了,Bar可以活下去。

public class Foo { 
    private Bar bar; 
    Foo(Bar bar) { 
       this.bar = bar; 
    }
}

摘自Robert Martin在comp.object中的一篇文章:

关联表示一个实例向另一个实例发送消息的能力。这通常是通过指针或引用实例变量实现的,尽管它也可以实现为一个方法参数,或创建一个局部变量。

//[Example:]

//|A|----------->|B|

class A
{
  private:
    B* itsB;
};

聚合[…是典型的整体/部分关系。这与实例不能具有循环聚合关系(即部分不能包含其整体)的异常关联完全相同。

//[Example:]

//|Node|<>-------->|Node|

class Node
{
  private:
    vector<Node*> itsNodes;
};

这是聚合的事实意味着Node的实例不能形成一个循环。因此,这是一个节点树,而不是节点图。

成分[…和聚合完全一样,只是“部分”的生命周期由“整体”控制。这种控制可以是直接的,也可以是传递的。也就是说,“整体”可以直接负责创造或破坏“部分”,或者它可以接受一个已经创建的部分,然后将它传递给其他某个整体,由其承担责任。

//[Example:]

//|Car|<#>-------->|Carburetor|

class Car
{
  public:
    virtual ~Car() {delete itsCarb;}
  private:
    Carburetor* itsCarb
};

我想说明如何在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

关联是两个独立的类之间的关系,关联可以是任何类型,比如one to one, one to may等等。它连接了两个完全独立的实体。

聚合是一种特殊形式的关联,它是类(或实体)之间的单向关系,例如钱包类和货币类。钱包里有钱,但钱不一定要有钱包,所以这是一种单向关系。在这种关系中,如果另一个条目结束,两个条目都可以存活。在我们的例子中,如果Wallet类不存在,并不意味着Money类不存在。

复合是聚合的一种受限形式,其中两个实体(或者可以说类)高度依赖于彼此。例如:人与心。人需要心脏才能生存,心脏也需要人体才能生存。换句话说,当类(实体)是相互依赖的,它们的生命周期是相同的(如果一个死了,另一个也死了),那么它就是一个复合。如果人类职业不存在,心脏职业就没有意义。

这些答案的问题在于,它们只说了一半:它们解释了聚合和组合是关联的形式,但没有说一个关联是否可能不是这两种形式。

基于对SO和一些UML文档的一些简要阅读,我收集到类关联有4种主要的具体形式:

A是由A组成的;没有A, B就不存在,就像家里的房间一样 聚合:A有A B;B可以没有A而存在,就像教室里的学生一样 依赖:A使用B;A和B之间没有生命周期依赖关系,比如方法调用参数、返回值或方法调用期间创建的临时对象 泛化:A是A

当两个实体之间的关系不是其中之一时,它可以被称为一般意义上的“关联”,并以其他方式进一步描述(注意,原型等)。

我的猜测是,“通用关联”主要用于两种情况:

when the specifics of a relationship are still being worked out; such relationship in a diagram should be converted as soon as possible to what it actually is/will be (one of the other 4). when a relationship doesn't match any of those 4 predetermined by UML; the "generic" association still gives you a way of representing a relationship that is "not one of the other ones", so that you aren't stuck using an incorrect relationship with a note "this is not actually aggregation, it's just that UML doesn't have any other symbol we could use"