组合关系和关联关系有什么区别?

23
在面向对象编程中,组合关系(用实心菱形在UML中表示)和关联关系(用空心菱形在UML中表示)的区别是什么?我有点困惑。什么是聚合?能否给出一个令人信服的现实世界的例子?

3
你是不是指的聚合(Aggregation)而不是关联(Association)? - Joey
1
关联不同于聚合;在UML中,聚合用空菱形表示。 - Rob
面向对象编程(OOP)! - blitzkriegz
8个回答

37

组合

想象一个软件公司,由不同的业务单元(或部门)组成,如存储BU、网络BU、汽车BU。这些业务单元的寿命受组织的寿命所支配。换句话说,这些业务单元不能独立于公司存在。这就是组合。(即公司由业务单元组成)

关联

软件公司可能有外部餐饮服务商为员工提供食品。这些餐饮服务商不是公司的一部分。但是,它们与公司有联系。如果我们的软件公司关闭了,餐饮服务商仍然可以存在。他们可以为其他公司服务!因此,餐饮服务商的寿命不受软件公司的寿命所支配。这是典型的关联。

聚合

考虑一个汽车制造单元。我们可以将汽车视为一个整体实体,而汽车轮胎则是汽车的一部分。(此时,它可能看起来像组合。等一下)轮胎可以在几周前创建,并可以存放在仓库中,然后在组装过程中放置在汽车上。在这个例子中,车轮类的实例明显独立于汽车类的实例的生命周期。因此,与组合不同,在聚合中,涉及到的对象的生命周期没有紧密耦合。


9
关联和聚合之间的区别是什么? - nawfal
很好的例子,但您能否提供一般性的解释?我知道问题并没有要求这样做。谢谢。 - chischaschos
@nawfal,从上面的例子中看来,部分独立于整体而存在。 - charany1

19

以下是几个例子:

  • 我是一家公司的员工,因此与该公司有关联。 我不是公司的一部分,也不是组成它的一部分,但与它有关联。

  • 我由器官组成,除非进行移植,否则这些器官将随我的死亡而消失。这就是组成,它是物体之间非常牢固的联系。基本上物体是由其他物体组成的。动词说出了一切。

  • 还有另一种不太紧密的组成方式,称为聚合。当物体由其他物体组成时,它们的生命周期并不一定相互关联。举个极端的例子,乐高玩具是由各种零件组成的聚合体。即使可以拆卸玩具,但其部件可以重新组合成一个不同的玩具。


11
拥有和使用。
组合:具有引用的对象“拥有”所引用的对象,并对其“生命周期”、销毁(通常还包括创建,虽然可以传递)负责。也称为“具有”关系。
关联:具有引用的对象“使用”所引用的对象,可能不是唯一的用户,并且不负责所引用对象的生命周期。也称为“使用”关系。
OP评论:
可以提供一个现实世界的例子吗?还有,什么是聚合?- Marc
聚合:从整体到部分的关联,不可循环。
例子:
组合:汽车拥有发动机,人拥有地址。基本上必须拥有并控制生命周期。
关联:汽车有司机,某个类实例有错误记录器。生命周期未受控制,可能被共享。
聚合:DOM(文档对象模型,即构成HTML元素树的对象)节点有一个(数组)子节点。节点是顶级的(嗯,更高级的);它“包含”其子节点,而不是反过来。

你能提供一个真实世界的例子吗?另外,什么是聚合? - Marc
1
根据Sommerville,Car-engine是聚合关系。has-a关系意味着聚合而非组合。组合是部分关系。"Person has-an Address"也是一个聚合关系,参考http://www.c-sharpcorner.com/UploadFile/pcurnow/compagg07272007062838AM/compagg.aspx。 - Slazer

4

我相信一个基于代码的例子可以帮助说明上述回答中提到的概念。

import java.util.ArrayList;

public final class AssoCia
{
    public static void main( String args[] )
    {
        B b = new B();
        ArrayList<C> cs = new ArrayList();

        A a = new A( b, cs );

        a.addC( new C() );
        a.addC( new C() );
        a.addC( new C() );
        a.listC();
    }
}

class A
{
    // Association -
    // this instance has a object of other class
    // as a member of the class.
    private B b;

    // Association/Aggregation -
    // this instance has a collection of objects
    // of other class and this collection is a
    // member of this class
    private ArrayList<C> cs;

    private D d;

    public A(B b, ArrayList<C> cs)
    {
        // Association
        this.b = b;

        // Association/Aggregation
        this.cs = cs;

        // Association/Composition -
        // this instance is responsible for creating
        // the instance of the object of the
        // other class. Therefore, when this instance 
        // is liberated from the memory, the object of
        // the other class is liberated, too.
        this.d = new D();
    }

    // Dependency -
    // only this method needs the object
    // of the other class.
    public void addC( C c )
    {
        cs.add( c );
    }

    public void listC()
    {
        for ( C c : cs )
        {
            System.out.println( c );
        }
    }

}

class B {}

class C {}

class D {}

2

独立存在。

发票由行项目组成。

如果一个行项目不在发票上,那它就是——嗯——什么也不是。它不能独立存在。

另一方面,发票与客户关联。

客户具有独立的存在,无论是否有发票。

如果两个事物具有独立存在,则它们可以相互关联。

如果一个事物不能独立存在,则它是构成的一部分。


1
通常,组合意味着包含对象的生命周期受到容器的限制,而关联是对一个可能独立存在的对象的引用。
然而,这只是我观察到的惯例。我不得不承认,研究UML2规范并不是我乐于做的事情!

1

组合关系比聚合关系更严格。组合意味着某物与另一物之间的关系非常紧密,它们基本上不能独立存在,或者如果可以,它们生活在不同的上下文中。

现实世界的例子:您定义了一个GUI窗口,然后是一个文本字段用于编写内容。在定义GUI的类和定义文本字段的类之间存在组合关系。它们一起组成一个小部件,可以被视为一个实体。假设您删除了窗口,也删除了文本字段。

聚合则不同,因为两个实体之间的链接是暂时的、不稳定的和偶然的。现实世界的例子。假设您有一个包含多个数据实例的对象数据库。现在您运行一些过滤器来收集符合给定标准的数据实例,并将结果实例推送到图形列表中,以便用户可以看到它们。当图形小部件接收到对象时,它可以形成这些实体的聚合,并呈现它们。如果用户关闭带有图形列表的窗口,并且后者被删除,则不应删除数据对象。也许它们在其他地方显示,或者您仍然需要它们。

此外,通常在创建时定义组合关系。相反,聚合在对象生命周期后定义。


0

组合意味着实体状态的一部分被另一种类型封装,但在概念上是实体状态的一部分。例如,您可能有一个地址类型和一个包括地址的员工实体类型。

关联意味着一个实体类型与另一个实体类型相关联,但相关联的实体在概念上不是实体状态的一部分。例如,员工可能与公司相关联。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接