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


我想这个链接可以帮到你:http://ootips.org/uml-hasa.html

为了理解这些术语,我记得我早期编程时的一个例子:

如果你有一个" chess board "对象它包含" box "对象那就是组合因为如果" chess board "被删除了盒子就没有理由再存在了。

如果你有一个'square'对象,它有一个'color'对象,正方形被删除了,'color'对象可能仍然存在,这就是聚合

它们都是关联,主要的区别是概念上的


正如其他人所说,关联是对象之间的关系,聚合和组合是关联的类型。

从实现的角度来看,聚合是通过引用类成员来获得的。例如,如果类A聚合类B的一个对象,你会有这样的东西(在c++中):

class A {
    B & element;
  // or B * element;
};

聚合的语义是,当对象A被销毁时,它所存储的对象B仍然存在。当使用组合时,你有一个更强的关系,通常通过按值存储成员:

class A {
    B element;
};

在这里,当一个A对象被销毁时,它所包含的B对象也将被销毁。最简单的方法是按值存储成员,但你也可以使用智能指针,或在析构函数中删除成员:

class A {
    std::auto_ptr<B> element;
};

class A {
    B * element;

    ~A() {
        delete B;
    }
};

重要的一点是,在组合中,容器对象拥有被包含的对象,而在聚合中,它引用它。


摘自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
};

对于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; 
    }
}

我知道这个问题被标记为c#,但概念是非常一般的问题,就像这里的这个重定向。所以我将在这里提供我的观点(从java的角度来看,我更舒服)。

当我们想到面向对象的本质时,我们总是想到对象、类(对象蓝图)以及它们之间的关系。对象之间通过方法相互关联和交互。换句话说,一个类的对象可以使用另一个类的对象提供的服务/方法。这种关系被称为关联。

聚合和组合是关联的子集,这意味着它们是关联的特定情况。

In both aggregation and composition object of one class "owns" object of another class. But there is a subtle difference. In Composition the object of class that is owned by the object of it's owning class cannot live on it's own(Also called "death relationship"). It will always live as a part of it's owning object where as in Aggregation the dependent object is standalone and can exist even if the object of owning class is dead. So in composition if owning object is garbage collected the owned object will also be which is not the case in aggregation.

困惑吗?

组合示例:以一辆汽车为例,它的发动机是这辆汽车特有的(意味着它不能用于任何其他汽车)。Car和SpecificEngine类之间的这种关系称为Composition。Car类的对象如果没有SpecificEngine类的对象就不能存在,而如果没有Car类,SpecificEngine的对象就没有意义。简单地说,Car类单独“拥有”SpecificEngine类。

聚合示例:现在考虑类Car和类Wheel。Car需要一个Wheel对象来运行。这意味着Car对象拥有Wheel对象,但我们不能说没有Car对象,Wheel对象就没有意义。它可以很好地用于自行车,卡车或不同的汽车对象。

总结一下

总而言之,关联是一个非常通用的术语,用于表示一个类使用另一个类提供的功能。如果一个父类对象拥有另一个子类对象,并且没有父类对象,这个子类对象就不能有意义地存在,我们就说它是复合。如果可以,则称为聚合。

详情请点击这里。 我是http://opensourceforgeeks.blogspot.in的作者,并在上面添加了相关帖子的链接以获取更多信息。


联想是关系的广义概念。它包括组合和聚合。

组合(混合)是一种将简单对象或数据类型包装成单个单元的方法。组合是许多基本数据结构的关键构建块

聚合(将许多事物形成一个集群)不同于普通的组合,因为它不意味着所有权。在组合中,当拥有的对象被销毁时,包含的对象也被销毁。总的来说,这并不一定正确。

记住区别的技巧:

“有一个”:聚合 “局部”: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大学有多个系,每个系都有一些教授。如果大学关闭,这些部门将不复存在,但这些部门的教授将继续存在。因此,一所大学可以被看作是一个系的组成部分,而系则是教授的集合。此外,教授可以在一个以上的部门工作,但一个部门不能属于一所以上的大学。


依赖性(引用) 这意味着两个物体之间没有概念上的联系。例如: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();
    }
}

令人惊讶的是,关于关联、聚合和组合这三个关系概念之间的区别存在如此多的混淆。

请注意,术语聚合和组合已经在c++社区中使用,可能在它们被定义为UML类图中关联的特殊情况之前已经有一段时间了。

主要的问题是广泛的和持续的误解(甚至在专家软件开发人员中),组合的概念意味着整体和它的部分之间的生命周期依赖关系,以至于部分不能没有整体而存在,忽略了这样一个事实,即也存在与不可共享部分的部分-整体-关联的情况,其中部分可以从整体中分离出来,并且在整体被破坏后仍然存在。

在我看来,这种困惑有两个根源:

In the C++ community, the term "aggregation" was used in the sense of a class defining an attribute for referencing objects of another independent class (see, e.g., [1]), which is the sense of association in UML Class Diagrams. The term "composition" was used for classes that define component objects for their objects, such that on destruction of the composite object, these component objects are being destroyed as well. In UML Class Diagrams, both "aggregation" and "composition" have been defined as special cases of associations representing part-whole relationships (which have been discussed in philosophy for a long time). In their definitions, the distinction between an "aggregation" and a "composition" is based on the fact if it allows sharing a part between two or more wholes. They define "compositions" as having non-shareable (exclusive) parts, while "aggregations" may share their parts. In addition they say something like the following: very often, but not in all cases, compositions come with a life-cycle dependency between the whole and its parts such that the parts cannot exist without the whole.

因此,尽管UML将术语“聚合”和“组合”放在了正确的上下文中(部分-整体关系),但是他们并没有设法以一种清晰和明确的方式来定义它们,从而捕捉开发人员的直觉。然而,这并不奇怪,因为这些关系可以有很多不同的属性(和实现的细微差别),开发人员对如何实现它们没有一致的意见。

请参见我对2009年4月SO问题的扩展回答。

c++社区中定义OOP对象之间“组合”的属性(这个信念仍然被广泛持有):两个相关对象(组合及其组件)之间的运行时生命周期依赖关系并不是“组合”的真正特征,因为在其他类型的关联中,我们也可以由于引用完整性而具有这种依赖关系。

例如,在一个SO回答中提出了以下“composition”的代码模式:

final class Car {    
  private final Engine engine;

  Car(EngineSpecs specs) {
    engine = new Engine(specs);
  }

  void move() {
    engine.work();
  }
}

被调查者声称这是“合成”的特征,没有其他类可以引用/知道这个组件。然而,并非所有可能的“组合”情况都是如此。特别是,在汽车引擎的情况下,汽车的制造商(可能是在另一个类的帮助下实现的)可能必须引用引擎,以便在出现问题时能够联系汽车的所有者。

[1] http://www.learncpp.com/cpp-tutorial/103-aggregation/

附录-关于StackOverflow上的组合与聚合的反复询问问题的不完整列表

[Apr 2009] Aggregation versus Composition [closed as primarily opinion-based by] [Apr 2009] What is the difference between Composition and Association relationship? [May 2009] Difference between association, aggregation and composition [May 2009] What is the difference between composition and aggregation? [duplicate] [Oct 2009] What is the difference between aggregation, composition and dependency? [marked as duplicate] [Nov 2010] Association vs. Aggregation [marked as duplicate] [Aug 2012] Implementation difference between Aggregation and Composition in Java [Feb 2015] UML - association or aggregation (simple code snippets)


协会

关联表示两个类之间的关系。它可以是单向的(单向)或双向的(双向)

例如:

单向

客户下单

双向

A和B结婚了 B和A结婚了

聚合

聚合是一种关联。但是有特定的特征。聚合是一个较大的“整体”类包含一个或多个较小的“部分”类之间的关系。相反,一个较小的“部分”类是“整个”较大类的一部分。

例如:

俱乐部有会员

一个俱乐部(“整体”)是由几个俱乐部成员(“部分”)组成的。会员可以在俱乐部外生活。如果俱乐部(“整体”)死亡,成员(“部分”)不会随之死亡。因为会员可以属于多个俱乐部(“整体”)。

作文

这是一种更强的聚合形式。“整体”对其“部分”的创造或破坏负责

例如:

学校有院系

在这种情况下,学校(“整体”)将消亡,部门(“部分”)将随之消亡。 因为每个部分只能属于一个“整体”。


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

基于对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"


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



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

成分: 一旦你摧毁了一个对象(学校),另一个与之绑定的对象(教室)也会被摧毁。两者都不能独立存在。

聚合: 这与上面的(Composition)关联完全相反,在上面的关联中,一旦你杀死了一个对象(Company),绑定到它的另一个对象(Employees)就可以独立存在。

协会。 组合和聚合是关联的两种形式。


组合(如果你删除“整体”,“部分”也会自动删除-“所有权”)

在新类中创建现有类的对象。这称为组合,因为新类是由现有类的对象组成的。 通常使用普通成员变量。 如果组合类自动处理负责创建/销毁子类的分配/回收,则可以使用指针值。

c++中的复合

#include <iostream>
using namespace std;
/********************** Engine Class ******************/
class Engine
{
    int nEngineNumber;
    public:
    Engine(int nEngineNo);
    ~Engine(void);
};
Engine::Engine(int nEngineNo)
{
    cout<<" Engine :: Constructor " <<endl;
}
Engine::~Engine(void)
{
    cout<<" Engine :: Destructor " <<endl;
}
/********************** Car Class ******************/
class Car
{
    int nCarColorNumber;
    int nCarModelNumber;
    Engine objEngine;
    public:
    Car (int, int,int);
    ~Car(void);
};
Car::Car(int nModelNo,int nColorNo, int nEngineNo):
nCarModelNumber(nModelNo),nCarColorNumber(nColorNo),objEngine(nEngineNo)
{
    cout<<" Car :: Constructor " <<endl;
}
Car::~Car(void)
{
    cout<<" Car :: Destructor " <<endl;
    Car
    Engine
    Figure 1 : Composition
}
/********************** Bus Class ******************/
class Bus
{
    int nBusColorNumber;
    int nBusModelNumber;
    Engine* ptrEngine;
    public:
    Bus(int,int,int);
    ~Bus(void);
};
Bus::Bus(int nModelNo,int nColorNo, int nEngineNo):
nBusModelNumber(nModelNo),nBusColorNumber(nColorNo)
{
    ptrEngine = new Engine(nEngineNo);
    cout<<" Bus :: Constructor " <<endl;
}
Bus::~Bus(void)
{
    cout<<" Bus :: Destructor " <<endl;
    delete ptrEngine;
}
/********************** Main Function ******************/
int main()
{
    freopen ("InstallationDump.Log", "w", stdout);
    cout<<"--------------- Start Of Program --------------------"<<endl;
    // Composition using simple Engine in a car object
    {
        cout<<"------------- Inside Car Block ------------------"<<endl;
        Car objCar (1, 2,3);
    }
    cout<<"------------- Out of Car Block ------------------"<<endl;
    // Composition using pointer of Engine in a Bus object
    {
        cout<<"------------- Inside Bus Block ------------------"<<endl;
        Bus objBus(11, 22,33);
    }
    cout<<"------------- Out of Bus Block ------------------"<<endl;
    cout<<"--------------- End Of Program --------------------"<<endl;
    fclose (stdout);
}

输出

--------------- Start Of Program --------------------
------------- Inside Car Block ------------------
Engine :: Constructor
Car :: Constructor
Car :: Destructor
Engine :: Destructor
------------- Out of Car Block ------------------
------------- Inside Bus Block ------------------
Engine :: Constructor
Bus :: Constructor
Bus :: Destructor
Engine :: Destructor
------------- Out of Bus Block ------------------
--------------- End Of Program --------------------

聚合(如果你删除“整体”,“部分”可以存在-“无所有权”)

聚合是一种特定类型的组合,其中不暗示复杂对象和子对象之间的所有权。当一个聚合被销毁时,子对象不会被销毁。 通常使用指针变量/引用变量指向在聚合类作用域之外的对象 可以使用指向在聚合类范围之外的对象的引用值吗 不负责创建/销毁子类

c++中的聚合代码

#include <iostream>
#include <string>
using namespace std;
/********************** Teacher Class ******************/
class Teacher
{
    private:
    string m_strName;
    public:
    Teacher(string strName);
    ~Teacher(void);
    string GetName();
};
Teacher::Teacher(string strName) : m_strName(strName)
{
    cout<<" Teacher :: Constructor --- Teacher Name :: "<<m_strName<<endl;
}
Teacher::~Teacher(void)
{
    cout<<" Teacher :: Destructor --- Teacher Name :: "<<m_strName<<endl;
}
string Teacher::GetName()
{
    return m_strName;
}
/********************** Department Class ******************/
class Department
{
    private:
    Teacher *m_pcTeacher;
    Teacher& m_refTeacher;
    public:
    Department(Teacher *pcTeacher, Teacher& objTeacher);
    ~Department(void);
};
Department::Department(Teacher *pcTeacher, Teacher& objTeacher)
: m_pcTeacher(pcTeacher), m_refTeacher(objTeacher)
{
    cout<<" Department :: Constructor " <<endl;
}
Department::~Department(void)
{
    cout<<" Department :: Destructor " <<endl;
}
/********************** Main Function ******************/
int main()
{
    freopen ("InstallationDump.Log", "w", stdout);
    cout<<"--------------- Start Of Program --------------------"<<endl;
    {
        // Create a teacher outside the scope of the Department
        Teacher objTeacher("Reference Teacher");
        Teacher *pTeacher = new Teacher("Pointer Teacher"); // create a teacher
        {
            cout<<"------------- Inside Block ------------------"<<endl;
            // Create a department and use the constructor parameter to pass the teacher to it.
            Department cDept(pTeacher,objTeacher);
            Department
            Teacher
            Figure 2: Aggregation
        } // cDept goes out of scope here and is destroyed
        cout<<"------------- Out of Block ------------------"<<endl;
        // pTeacher still exists here because cDept did not destroy it
        delete pTeacher;
    }
    cout<<"--------------- End Of Program --------------------"<<endl;
    fclose (stdout);
}

输出

--------------- Start Of Program --------------------
Teacher :: Constructor --- Teacher Name :: Reference Teacher
Teacher :: Constructor --- Teacher Name :: Pointer Teacher
------------- Inside Block ------------------
Department :: Constructor
Department :: Destructor
------------- Out of Block ------------------
Teacher :: Destructor --- Teacher Name :: Pointer Teacher
Teacher :: Destructor --- Teacher Name :: Reference Teacher
--------------- End Of Program --------------------

在一个非常简单的句子中: 聚合和组合是关联的子集。

A使用B ->这是一个聚合 A需要B ->是复合。

点击这里阅读更多。


    Simple rules:
    A "owns" B = Composition : B has no meaning or purpose in the system 
    without A
    A "uses" B = Aggregation : B exists independently (conceptually) from A
    A "belongs/Have" B= Association; And B exists just have a relation
    Example 1:

    A Company is an aggregation of Employees.
    A Company is a composition of Accounts. When a Company ceases to do 
    business its Accounts cease to exist but its People continue to exist. 
    Employees have association relationship with each other.

    Example 2: (very simplified)
    A Text Editor owns a Buffer (composition). A Text Editor uses a File 
    (aggregation). When the Text Editor is closed,
    the Buffer is destroyed but the File itself is not destroyed.

摘自: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.

我们称这些关系为聚合,其对象具有独立的生命周期,但存在所有权,并且子对象不能属于另一个父对象。让我们以手机和电池为例。单个电池可以属于一个手机,但如果手机停止工作,我们从数据库中删除它,手机电池将不会被删除,因为它可能仍在工作。因此,在聚合中,虽然有所有权,但对象有它们的生命周期

我们使用术语组合来指代对象没有独立生命周期的关系,如果父对象被删除,所有子对象也将被删除。让我们以问题和答案之间的关系为例。一个问题可以有多个答案,答案不能属于多个问题。如果我们删除问题,答案将自动删除。


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

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

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


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”类型的关系,反之亦然。


关联、聚合、组合

关联、聚合、组合都是有关系的。

聚合和组合是关联的子集,它们更准确地描述了关系

与聚合无关的关系。一个对象可以通过构造函数、方法、setter传递和保存在类中…

成分依赖关系。对象由所有者对象创建

关联是sybtyping的另一种选择


在面向对象编程中,类是相互关联的。这意味着它们的实例相互调用方法。因此,如果一个类的实例调用另一个类的方法,它们是相关的,通常我们用ASSOCIATION来建模这种关系。 例如,在下面的代码片段中,Customer类与Order类相关联。她/他取消了订单。

class Customer {
        private Order[] orders;
        public boolean removeCart() {
                for (int i = 0 ; i < orders.length ; i++) {
                        orders[i].cancel();
                }
        }
}

AGGREGATION意味着一个类拥有另一个类的一些实例。它只不过是联想,马丁·福勒建议不要使用它。因为当一个类与另一个类相关联时,它有一个对该类的引用来调用该类上的方法。

但是COMPOSITION是关联的一个有意义的子集。这意味着一个类是由其他一些类组成的。例如,我们有一个学生类,由其他一些类组成,如ReportCard。我们知道成绩单是非常依赖于学生的,如果我们从系统中删除了学生,他们的成绩单也应该被删除。