Java中聚合与组合的实现差异


102

我知道聚合和组合之间的概念差异。有人可以通过示例告诉我它们在Java中的实现差异吗?


3
点击此链接,您可能会回答您的帖子[聚合和组成之间的差异] [1] [1]:stackoverflow.com/a/1468285/1353243
gks 2012年



当我们在对象之间有任何关系时,就称为关联。聚合和组合都是协会的专门形式。组合还是聚集的专门形式。 javabench.in/2011/08/difference-between-association.html
劳尔

Answers:


222

组成

final class Car {

  private final Engine engine;

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

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

聚合

final class Car {

  private Engine engine;

  void setEngine(Engine engine) {
    this.engine = engine;
  }

  void move() {
    if (engine != null)
      engine.work();
  }
}

在组成的情况下,引擎完全由汽车封装。外界无法获得对引擎的引用。引擎随汽车而死。通过聚合,汽车还可以通过引擎执行其功能,但是引擎并不总是汽车的内部部分。引擎可能会被交换,甚至被完全删除。不仅如此,外界仍然可以引用引擎,并且可以修改引擎,而不管它是否在汽车中。


7
很好的例子!它还将组合显示为强关联(没有引擎的Car毫无意义),将聚合显示为弱关联(没有引擎的Car完全有意义,甚至在其构造函数中都不需要)。使用哪一个?取决于上下文。
Federico Pugnali 2012年

@Anand您在Aggregation中给出的示例不是这个依赖示例吗?依赖关系是一种较弱的关系形式,用代码术语表示,一个类使用另一个按参数或返回类型的类。
OOkhan

@Anand:你能解释为什么你说的更多:在合成的情况下,外界无法获得对Engine的引用,通过汇总,外界可以引用Engine?您可以在代码示例中显示外界如何或不能参考引擎吗?谢谢
O Connor

9
这不是正确的例子。外部世界可以访问内部对象,但是其标识始终与外部对象相关联,而在聚集时,即使没有汽车,内部对象也可能独立存在。在这种情况下,new Engine(EngineSpecs)即使没有汽车,仍可以使用呼叫创建引擎。实现组合的方法是将Engine创建为内部类,以便始终参照汽车对象创建引擎的对象
mickeymoon

@mickeymoon很棒。您能指出一个更好的例子吗?
Gayan Weerakutti

19

我将使用一个不错的UML示例。

以一所拥有1至20个不同系的大学为例,每个系有1至5个教授。大学与其各系之间存在着组成联系。一个系和它的教授之间有一个聚合的联系。

组成只是强大的聚集,如果大学被摧毁,那么系也应该被摧毁。但是,即使他们各自的系消失了,我们也不应该杀死教授。

在java中:

public class University {

     private List<Department> departments;

     public void destroy(){
         //it's composition, when I destroy a university I also destroy the departments. they cant live outside my university instance
         if(departments!=null)
             for(Department d : departments) d.destroy();
         departments.clean();
         departments = null;
     }
}

public class Department {

     private List<Professor> professors;
     private University university;

     Department(University univ){
         this.university = univ;
         //check here univ not null throw whatever depending on your needs
     }

     public void destroy(){
         //It's aggregation here, we just tell the professor they are fired but they can still keep living
         for(Professor p:professors)
             p.fire(this);
         professors.clean();
         professors = null;
     }
}

public class Professor {

     private String name;
     private List<Department> attachedDepartments;

     public void destroy(){

     }

     public void fire(Department d){
         attachedDepartments.remove(d);
     }
}

周围的东西。


我希望我不会对未初始化的列表和构造函数没有任何评论。我写得很快,缺少的部分是常识,但是如果被问到我将完成解决方案
TecHunter 2012年

谢谢!您的例子很清楚。但我不明白您的代码说明。您能告诉我两者的基本区别吗?如果必须实现聚合或组合,应该使用Java中的哪些概念?
Rajath

如果您要讨论类BUT组成,则应该通过管理实例的方式(例如在我的编辑中)来反映出完全相同的实现
TecHunter 2012年


3

区别在于,任何组合都是聚合,而不是相反。

让我们设置条件。聚合是UML标准中的一个元术语,表示合并和共享聚合,简称为shared。它经常被错误地命名为“聚合”。它是BAD,因为组合也是聚合。据我了解,您的意思是“共享”。

与UML标准相比:

复合-表示属性是复合聚合的,即复合对象负责组成对象(部件)的存在和存储。

因此,大学到Cathedras协会是一个组成部分,因为Cathedra不存在于University(IMHO)之外

共享聚合的精确语义因应用程序区域和建模器而异。

即,如果您仅遵循自己或他人的某些原则,则可以将所有其他关联绘制为共享聚合。也看这里


3

简单来说 :

组合和聚合都是关联。组成->严格的Has-A关系聚合->弱的Has-A关系。


2

一个简单的合成程序

public class Person {
    private double salary;
    private String name;
    private Birthday bday;

    public Person(int y,int m,int d,String name){
        bday=new Birthday(y, m, d);
        this.name=name;
    }


    public double getSalary() {
        return salary;
    }

    public String getName() {
        return name;
    }

    public Birthday getBday() {
        return bday;
    }

    ///////////////////////////////inner class///////////////////////
    private class Birthday{
        int year,month,day;

        public Birthday(int y,int m,int d){
            year=y;
            month=m;
            day=d;
        }

        public String toString(){
           return String.format("%s-%s-%s", year,month,day);

        }
    }

    //////////////////////////////////////////////////////////////////

}
public class CompositionTst {

    public static void main(String[] args) {
        // TODO code application logic here
        Person person=new Person(2001, 11, 29, "Thilina");
        System.out.println("Name : "+person.getName());
        System.out.println("Birthday : "+person.getBday());

        //The below object cannot be created. A bithday cannot exixts without a Person 
        //Birthday bday=new Birthday(1988,11,10);

    }
}

2

首先,我们必须讨论AggregationComposition在同一页面上到底有什么区别。

聚集是关联实体可以独立于关联而存在的关联。例如,一个人可能与一个组织相关联,但他/她在系统中可能具有独立的存在。

组成是指其中一个关联实体与另一个实体密切相关,并且在没有另一个实体存在的情况下不存在的情况。实际上,该实体的身份始终与另一个对象的身份相关联。例如,车轮进入汽车。

现在,可以通过将一个实体的属性保留在另一个实体中来简单地实现聚合,如下所示:

class Person {
    Organisation worksFor;
}

class Organisation {
    String name;
}

class Main {
    public static void main(String args[]) {

        //Create Person object independently
        Person p = new Person();

        //Create the Organisation independently
        Organisation o = new Organisation();
        o.name = "XYZ Corporation";

        /*
          At this point both person and organisation 
          exist without any association  
        */
        p.worksFor = o;

    }
}

对于“合成”,必须始终使用其关联对象的标识来创建从属对象。您可以为它使用内部类。

class Car {
    class Wheel {
        Car associatedWith;
    }
}

class Main {
    public static void main() {
        //Create Car object independently
        Car car = new Car();

        //Cannot create Wheel instance independently
        //need a reference of a Car for the same.
        Car.Wheel wheel = car.new Wheel();
    }
}

请注意,根据应用场景,同一用例可能属于聚合/组成。例如,如果您正在为某个组织中的人员开发应用程序,并且必须要注册组织,则“人员组织”案例可能会变得复杂。同样,如果要维护汽车零件的库存,则“汽车—车轮”关系可以是聚合的。


1

聚合与构成

聚集意味着孩子可以独立于父母而存在的关系。例如,银行和雇员,删除银行和雇员仍然存在。

而“ 组合”则意味着孩子不能独立于父母而存在的关系。示例:人与心,心并不与人分开存在。

聚集关系是“具有”组成关系是“部分”关系。

组成是强关联,而聚集是弱关联。


0

这两种类型当然都是关联,并没有真正严格地映射到这样的语言元素。不同之处在于目的,上下文和系统建模方式。

举一个实际的例子,比较具有相似实体的两种不同类型的系统:

  • 主要用于跟踪汽车及其所有者等的汽车注册系统。在这里,我们对作为单独实体的引擎不感兴趣,但是我们可能仍具有与引擎相关的属性,例如功率和燃料类型。在这里,引擎可能是汽车实体的组成部分。

  • 汽车维修车间管理系统,用于管理汽车零件,维修汽车并更换零件,可能是完整的发动机。在这里,我们甚至可能储备了发动机,需要分别和独立于汽车来跟踪它们和其他零件。在这里,引擎可以是汽车实体的集合部分。

在您的语言中,如何实现此功能无关紧要,因为在该级别上,诸如可读性之类的东西更为重要。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.