107 votes

Différence de mise en œuvre entre l'agrégation et la composition en Java

Je suis conscient des différences conceptuelles entre l'agrégation et la composition. Quelqu'un peut-il me dire quelle est la différence d'implémentation en Java entre les deux, avec des exemples ?

3 votes

En suivant ce lien, vous obtiendrez peut-être une réponse à vos questions [Différence entre agrégation et composition] [1] [1] : stackoverflow.com/a/1468285/1353243

0 votes

Duplication possible de Agrégation ou composition

0 votes

231voto

Anand Points 2152

Composition

final class Car {

  private final Engine engine;

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

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

Agrégation

final class Car {

  private Engine engine;

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

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

Dans le cas de la composition, le moteur est complètement encapsulé dans la voiture. Il n'y a aucun moyen pour le monde extérieur d'obtenir une référence au moteur. Le moteur vit et meurt avec la voiture. Dans le cas de l'agrégation, la voiture exécute également ses fonctions par l'intermédiaire d'un moteur, mais celui-ci n'est pas toujours une partie interne de la voiture. Les moteurs peuvent être échangés, voire complètement supprimés. De plus, le monde extérieur peut toujours avoir une référence au moteur et le modifier, qu'il soit ou non dans la voiture.

7 votes

Excellent exemple ! Il montre également que la composition est une association forte (une voiture n'a aucun sens sans moteur) et que l'agrégation est une association faible (une voiture sans moteur est tout à fait logique, elle n'en a même pas besoin dans son constructeur). Laquelle utiliser ? Cela dépend du contexte.

0 votes

@Anand l'exemple que vous donnez dans Aggregation n'est-il pas un exemple de dépendance ? La dépendance est une forme plus faible de relation et, en termes de code, indique qu'une classe en utilise une autre par le biais d'un paramètre ou d'un type de retour.

0 votes

@Anand : pouvez-vous expliquer davantage pourquoi vous avez dit : dans le cas de la composition, il n'y a aucun moyen pour le monde extérieur d'obtenir une référence au moteur, avec l'agrégation, le monde extérieur peut avoir une référence au moteur ? Pouvez-vous montrer dans un exemple de code, comment le monde extérieur peut ou ne peut pas avoir une référence au moteur ? Merci.

21voto

TecHunter Points 2775

J'utiliserais un bon exemple UML.

Prenons l'exemple d'une université qui compte de 1 à 20 départements différents et où chaque département compte de 1 à 5 professeurs. Il existe un lien de composition entre une université et ses départements. Il existe un lien d'agrégation entre un département et ses professeurs.

La composition n'est qu'une agrégation FORTE, si l'université est détruite, les départements devraient l'être aussi. Mais nous ne devrions pas tuer les professeurs même si leurs départements respectifs disparaissent.

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

A peu près comme ça.

EDIT : un exemple comme demandé

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

    }

}

Classe universitaire

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

Classe de département

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

Classe de professeur

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

La mise en œuvre est discutable car elle dépend de la manière dont vous devez gérer la création, l'embauche, la suppression, etc. Sans rapport avec l'OP

0 votes

J'espère que je n'aurai pas de commentaire sur les listes non initialisées et l'absence de constructeurs. J'ai écrit cela rapidement, les parties manquantes relèvent du bon sens, mais si on me le demande, je complèterai la solution.

0 votes

Merci ! Votre exemple est parfaitement clair. Mais je n'ai pas compris l'illustration de votre code. Pouvez-vous m'indiquer le de base différence de mise en œuvre entre les deux ? Si je dois mettre en œuvre l'agrégation ou la composition, quels concepts de Java dois-je utiliser ?

0 votes

C'est exactement la même implémentation si l'on parle de classe MAIS la composition devrait être reflétée par la façon dont vous gérez les instances comme dans mon édition

5voto

Un programme de composition simple

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

    }
}

0 votes

Pouvez-vous également ajouter un code Java fonctionnel pour l'association et l'agrégation en expliquant tous les scénarios comme vous l'avez fait pour la composition ? 1. Scénarios dans l'association s'ils sont supprimés ? 2. Scénarios dans l'agrégation lorsque l'objet parent est supprimé ?

3voto

KVK Points 96

En termes simples :

La composition et l'agrégation sont toutes deux des associations. Composition -> relation Has-A forte Agrégation -> relation Has-A faible.

3voto

Gangnus Points 7646

La différence est que toute composition est une agrégation et non l'inverse.

Fixons les conditions. L'agrégation est un métaterme dans la norme UML, et signifie à la fois la composition et l'agrégation partagée, simplement nommée partagé . Trop souvent, on l'appelle à tort "agrégation". C'est une erreur, car la composition est aussi une agrégation. Si je comprends bien, vous voulez dire "partagé".

Plus loin que la norme UML :

c c'est-à-dire que l'objet composite est responsable de l'existence et de la l'existence et le stockage des objets composés (parties).

Ainsi, l'association entre l'université et les cathédrales est une composition, car les cathédrales n'existent pas en dehors de l'université (IMHO).

P modélisateur.

En d'autres termes, toutes les autres associations peuvent être considérées comme des agrégations partagées, si vous ne faites que suivre certains de vos principes ou ceux de quelqu'un d'autre. Regardez aussi ici .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X