Разница в реализации между агрегацией и компоновкой в ​​Java


103

Я знаю о концептуальных различиях между агрегированием и композицией. Может ли кто-нибудь сказать мне разницу в реализации на Java между ними на примерах?


3
Перейдя по этой ссылке, вы можете получить ответ на свои сообщения [Разница между агрегированием и композицией] [1] [1]: stackoverflow.com/a/1468285/1353243
gks



Когда у нас есть какое-либо отношение между объектами, это называется ассоциацией. И агрегирование, и композиция являются специализированной формой объединения. Состав снова является специализированной формой агрегирования. javabench.in/2011/08/difference-between-association.html
Рауль

Вы можете найти больше ответов здесь
hamed moosaei

Ответы:


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

В случае композиции Двигатель полностью заключен в машину. Внешний мир не может получить ссылку на Engine. Двигатель живет и умирает вместе с автомобилем. При агрегации автомобиль также выполняет свои функции через двигатель, но двигатель не всегда является внутренней частью автомобиля. Двигатели можно поменять местами или даже полностью снять. Более того, внешний мир все еще может иметь ссылку на Двигатель и работать с ним, независимо от того, находится ли он в Автомобиле.


7
Отличный пример! Он также показывает композицию как сильную ассоциацию (автомобиль не имеет смысла без двигателя), а агрегацию как слабую ассоциацию (автомобиль без двигателя имеет смысл, он даже не нужен в своем конструкторе). Какой использовать? Зависит от контекста.
Федерико Пугнали,

@An и пример, который вы приводите в Aggregation, не является ли это примером зависимости? Зависимость - это более слабая форма связи, и в терминах кода указывает, что класс использует другой по параметру или типу возвращаемого значения.
OOkhan 08

@Anand: не могли бы вы подробнее объяснить, почему вы сказали: в случае композиции у внешнего мира нет возможности получить ссылку на Engine, при агрегировании внешний мир может иметь ссылку на Engine? Можете ли вы показать в примере кода, как внешний мир может или не может иметь ссылку на движок? спасибо
О Коннор

9
Это неверный пример. Внешний мир может иметь доступ к внутреннему объекту, но его идентичность всегда связана с внешним объектом, в то время как в совокупности внутренний объект может существовать независимо, даже если машины не было. В этом случае двигатель все равно можно создать с помощью new Engine(EngineSpecs)вызова, даже если машины не было. Чтобы добиться композиции, нужно создать Engine как внутренний класс, чтобы объект Engine всегда создавался со ссылкой на объект Car
mickeymoon

@mickeymoon отличный улов. вы можете указать нам лучший пример?
Gayan Weerakutti

20

Я бы использовал хороший пример 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


Надеюсь, я не получу комментариев о неинициализированных списках и конструкторах. Я написал это быстро, недостающие части - это здравый смысл, но если меня спросят, я
дополню

Спасибо! Ваш пример совершенно ясен. Но я не мог понять вашу иллюстрацию кода. Можете ли вы рассказать мне об основных различиях в реализации между ними? Если мне нужно реализовать агрегирование или композицию, какие концепции в Java я должен использовать?
Rajath

это точно такая же реализация, если вы говорите о классе, НО композиция должна отражаться в том, как вы управляете экземплярами, как в моем редактировании
TecHunter

TecHunter, искал этот пример. Можете ли вы также расширить Java-код для демонстрации ассоциации на примере университета. Как следует запускать пример в методе main (). (который может показывать сценарии создания университета и удаления профессоров). Пожалуйста, помогите
deepakl.2000

@ deepakl.2000 много способов сделать это. Вы должны определить, какой класс имеет власть. это может быть профессор, поступающий в университет, а затем один на другой факультет, или это может быть то, что университет нанимает профессора, а затем просит факультет поступить. все дело в том, что больше подходит для ваших нужд.
TecHunter,

4

В приведенном ниже URL-адресе есть отличное объяснение.

введите описание изображения здесь

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

Пожалуйста, проверьте!!!


Привет, Рахул, хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменяется. Пожалуйста, посмотрите здесь: Почему и как удаляются некоторые ответы?
bummi 02

3

Простая программа композиции

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

    }
}

Не могли бы вы также добавить рабочий Java-код для ассоциации и агрегации, а также объяснить все сценарии, как вы объяснили в разделе «Композиция»? 1. Сценарии в ассоциации, если их удалить? 2. Сценарии агрегирования при удалении родительского объекта?
deepakl.2000

3

Разница в том, что любая композиция - это агрегирование, а не наоборот.

Установим сроки. Агрегация - это метатерм в стандарте UML, означающий ОБА композицию и общую агрегацию, просто называемую общим. . Слишком часто это неправильно называют «агрегацией». Это ПЛОХО, потому что композиция - это тоже агрегирование. Насколько я понял, вы имеете в виду «общий».

Дополнительно от стандарта UML:

составной - указывает на то, что свойство агрегировано составно, т. е. составной объект отвечает за существование и хранение составных объектов (частей).

Итак, ассоциация университета и кафедры - это композиция, потому что кафедра не существует вне университета (ИМХО).

Точная семантика совместной агрегации зависит от области приложения и разработчика.

Т.е. все остальные ассоциации можно нарисовать как общие агрегаты, если вы следуете только каким-то своим или чьим-то другим принципам. Также смотрите здесь .


3

Проще говоря:

И состав, и агрегирование являются ассоциациями. Состав -> Агрегация сильных отношений -> Отношения слабых отношений.


2

Сначала мы должны поговорить о том, в чем на самом деле разница между 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();
    }
}

Обратите внимание, что один и тот же вариант использования может подпадать под агрегацию / композицию в зависимости от сценария приложения. Например, случай «Человек-Организация» может стать составным, если вы разрабатываете приложение для людей, работающих в какой-либо организации, и для регистрации необходима ссылка на организацию. Точно так же, если вы ведете инвентарь для частей автомобиля, связь «автомобиль-колесо» может быть агрегированной.


1

Агрегация против композиции

Агрегация подразумевает отношения, в которых может существовать ребенок независимо от родителя. Например, Банк и Сотрудник, удалите Банк, и Сотрудник все еще существует.

тогда как композиция подразумевает отношения, при которых ребенок не может существовать независимо от родителя. Пример: Человек и сердце, сердце не существуют отдельно от Человека.

Отношение агрегации - это отношение «имеет», а композиция - отношение «часть из».

Состав - это сильная ассоциация, тогда как агрегирование - это слабая ассоциация.


0

Оба типа, конечно, являются ассоциациями и на самом деле не связаны строго с такими языковыми элементами. Разница заключается в цели, контексте и том, как моделируется система.

В качестве практического примера сравним два разных типа систем с похожими объектами:

  • Система регистрации автомобилей, которая в первую очередь отслеживает автомобили, их владельцев и т.д. Здесь Двигатель может быть составной частью автомобиля.

  • Система управления автосервисом, которая управляет автомобильными запчастями, обслуживает автомобили и заменяет детали, возможно, целые двигатели. Здесь у нас даже может быть запас двигателей, и нам нужно будет отслеживать их и другие части отдельно и независимо от автомобилей. Здесь Двигатель может быть агрегированной частью автомобиля.

То, как вы реализуете это на своем языке, не имеет большого значения, поскольку на этом уровне гораздо важнее такие вещи, как удобочитаемость.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.