111

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

4

9 回答 9

245

作品

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();
  }
}

在组合的情况下,Engine 完全被 Car 封装。外界无法获得对 Engine 的引用。引擎与汽车一起生死存亡。通过聚合,Car 也通过 Engine 执行其功能,但 Engine 并不总是 Car 的内部部分。引擎可能会被交换,甚至完全移除。不仅如此,外界仍然可以对 Engine 有一个引用,并且不管它是否在 Car 中,都可以对其进行修改。

于 2012-09-14T20:13:31.000 回答
22

我会使用一个很好的 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);
     }
}

这周围的东西。

编辑:根据要求提供一个示例

public class Test
{
    public static void main(String[] args)
    {
        University university = new University();
        //the department only exists in the university
        Department dep = university.createDepartment();
        // the professor exists outside the university
        Professor prof = new Professor("Raoul");
        System.out.println(university.toString());
        System.out.println(prof.toString());

        dep.assign(prof);
        System.out.println(university.toString());
        System.out.println(prof.toString());
        dep.destroy();

        System.out.println(university.toString());
        System.out.println(prof.toString());

    }


}

大学班

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class University {

    private List<Department> departments = new ArrayList<>();

    public Department createDepartment() {
        final Department dep = new Department(this, "Math");
        departments.add(dep);
        return dep;
    }

    public void destroy() {
        System.out.println("Destroying university");
        //it's composition, when I destroy a university I also destroy the departments. they cant live outside my university instance
        if (departments != null)
            departments.forEach(Department::destroy);
        departments = null;
    }

    @Override
    public String toString() {
        return "University{\n" +
                "departments=\n" + departments.stream().map(Department::toString).collect(Collectors.joining("\n")) +
                "\n}";
    }
}

部门班

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Department {

    private final String name;
    private List<Professor> professors = new ArrayList<>();
    private final University university;

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

    public void assign(Professor p) {
        //maybe use a Set here
        System.out.println("Department hiring " + p.getName());
        professors.add(p);
        p.join(this);
    }

    public void fire(Professor p) {
        //maybe use a Set here
        System.out.println("Department firing " + p.getName());
        professors.remove(p);
        p.quit(this);
    }

    public void destroy() {
        //It's aggregation here, we just tell the professor they are fired but they can still keep living
        System.out.println("Destroying department");
        professors.forEach(professor -> professor.quit(this));
        professors = null;
    }

    @Override
    public String toString() {
        return professors == null
                ? "Department " + name + " doesn't exists anymore"
                : "Department " + name + "{\n" +
                "professors=" + professors.stream().map(Professor::toString).collect(Collectors.joining("\n")) +
                "\n}";
    }
}

教授班

import java.util.ArrayList;
import java.util.List;

public class Professor {

    private final String name;
    private final List<Department> attachedDepartments = new ArrayList<>();

    public Professor(String name) {
        this.name = name;
    }

    public void destroy() {

    }

    public void join(Department d) {
        attachedDepartments.add(d);
    }

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

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Professor " + name + " working for " + attachedDepartments.size() + " department(s)\n";
    }
}

实施是有争议的,因为它取决于您需要如何处理创建、雇用删除等。与 OP 无关

于 2012-08-09T15:26:35.440 回答
5

一个简单的作曲程序

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);

    }
}
于 2014-01-16T03:27:24.523 回答
4

简单来说 :

组合和聚合都是关联。组合 -> 强 Has-A 关系 聚合 -> 弱 Has-A 关系。

于 2014-03-04T15:13:01.013 回答
4

下面给出的网址中有一个很好的解释。

在此处输入图像描述

http://www.codeproject.com/Articles/330447/Understanding-Association-Aggregation-and-Composit

请检查!!!

于 2015-08-02T06:05:25.350 回答
4

Aggregation首先,我们必须谈谈和Composition在同一页面上的实际区别。

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

然而

组合是指其中一个关联实体与另一个关联的实体密切相关,并且如果没有另一个实体的存在就无法存在。事实上,该实体的身份总是与另一个对象的身份相关联。例如,汽车的轮子。

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

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();
    }
}

请注意,根据应用场景,相同的用例可能属于聚合/组合。例如,如果您正在为在某个组织工作的人开发应用程序,并且必须引用组织以进行注册,则“个人-组织”案例可能会成为组合。同样,如果您要维护汽车零件的库存,则 Car-Wheel 关系可以是聚合的。

于 2016-02-04T22:06:03.900 回答
3

不同之处在于任何组合都是聚合,反之亦然。

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

进一步从 UML 标准:

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

因此,大学与大教堂协会是一个组合,因为大学不存在大教堂(恕我直言)

共享聚合的精确语义因应用领域和建模者而异。

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

于 2014-01-22T10:16:19.687 回答
3
于 2020-01-26T08:05:03.103 回答
1

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

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

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

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

你如何在你的语言中实现这一点是次要的,因为在那个级别上,可读性等事情要重要得多。

于 2016-08-24T19:52:03.310 回答