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

我知道聚合和组合在概念上的不同。有没有人能用例子告诉我它们在 Java 中的实现差异?

122338 次浏览

我会使用一个很好的 UML 示例。

Take a university that has 1 to 20 different departments and each department has 1 to 5 professors. There is a composition link between a University and its' departments. 在一个系和它的教授之间有一个聚合链接。

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

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

Something around this.

编辑: 按照要求的示例

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";
}
}

实现是有争议的,因为它取决于你需要如何处理创建,雇用删除等。与任务无关

作曲

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

在组成的情况下,发动机是完全封装的汽车。外部世界无法获得引擎的引用。永动机与汽车同生共死。通过聚合,Car 也通过 Engine 执行其功能,但 Engine 并不总是 Car 的内部部件。引擎可能被更换,甚至完全移除。不仅如此,外部世界仍然可以有一个引擎的参考,并与它修补不管它是否在车里。

A simple Composition program

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


}
}

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

我们来定条件吧。聚合是 UML 标准中的一个元术语,意味着组合和共享聚合,简称为 分享。它常常被错误地命名为“聚合”。这是糟糕的,因为组合也是一种聚合。据我所知,你的意思是“分享”。

远离 UML 标准:

composite - Indicates that the property is aggregated compositely, 即,复合对象对存在和 组合对象(部件)的存储。

因此,大学对大教堂的联想是一种组合,因为大教堂并不存在于大学之外(恕我直言)

共享聚合的精确语义因应用程序领域和 模特。

也就是说,如果你只是遵循自己或他人的某些原则,那么所有其他的关联都可以被描绘成共享的聚合。再看看 给你

In simple terms :

组合和聚合都是关联。 作曲-> 强有力-一段关系 聚合-> 弱有-一种关系。

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

enter image description here

Http://www.codeproject.com/articles/330447/understanding-association-aggregation-and-composit

请检查! ! !

First we must talk about what actually the difference between Aggregation and Composition is to be on the same page.

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

whereas

合成是指一个相关联的实体与另一个强烈相关,没有另一个实体的存在就不能存在的情况。事实上,该实体的标识总是与其他对象的标识相关联。例如,汽车的轮子。

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

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

请注意,根据应用程序场景的不同,相同的用例可能属于聚合/组合。例如,如果你正在为某个机构的工作人员开发一个应用程序,而该应用程序必须提及某个机构才能注册,那么“个人-机构”个案可能会变成组合。类似地,如果您维护汽车部件的库存,汽车-车轮关系可以是聚合的。

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

作为一个实际的例子,将两种不同类型的系统与相似的实体进行比较:

  • 一个汽车登记系统,主要跟踪汽车及其所有者等。在这里,我们不感兴趣的引擎作为一个单独的实体,但我们可能仍然有引擎相关的属性,如动力和燃料类型。这里的发动机可能是汽车实体的 合成的部分。

  • A car service shop management system that manages car parts, servicing cars, and replace parts, maybe complete engines. Here we may even have engines stocked and need to keep track of them and other parts separately and independent of the cars. Here the Engine may be an 聚合 part of the car entity.

如何在自己的语言中实现这一点并不重要,因为在这个层次上,可读性之类的东西要重要得多。

聚合与组合

聚合 意味着一种关系,其中 孩子可以存在独立于父级。例如,Bank 和 Employee,删除 Bank 和 Employee 仍然存在。

Composition意味着一种关系,其中 孩子不能存在独立于父级。例句: 人类和心脏,心脏不是独立于人类而存在的。

聚合关系是“ has-a” ,而“ strong”合成是“ part-of”关系。

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