Αυτές οι δύο έννοιες είναι πολύ κοντινές και πολλές φορές προκαλούν συγχύσεις.
Για αυτό ας ξεκαθαρίσουμε τις έννοιες αυτές.

  • Aggregation: χρησιμοποιώ όταν θέλω να περιγράψω αντικείμενα που έχουν αυτόνομη ύπαρξη και αποτελούν μέρος της σύνθεσης του όλου. Για παράδειγμα μια τάξη(το όλο) , (αποτελείται) έχει μαθητές.
  • Composition: χρησιμοποιώ όταν θέλω να περιγράψω αντικείμενα που δεν έχουν αυτόνομη ύπαρξη και αποτελούν αναπόσπαστο μέρος του όλου. Για παράδειγμα το σχολείο (το όλο), (αποτελείται) έχει τάξεις.


Σε κάθε περίπτωση θα πρέπει να υπάρξει μια προσεκτική ανάλυση της περιγραφής του προβλήματος που μας ζητούν να επιλύσουμε με java, καθώς και να παραθέσουμε τις κατάλληλες παραδοχές με τις αιτιολογήσεις μας για να έχουμε κάθε φορά σωστή απάντηση. Μην ξεχνάτε ότι στον προγραμματισμό και ιδίως στην ανάπτυξη αντικειμενοστραφών εφαρμογών έχουμε τα περιθώρια να υλοποιήσουμε μια εφαρμογή με πολλούς τρόπους ανάλογα τις παραδοχές και τον βαθμό ανάλυσης και κατανόησης του προβλήματος.
Όσο περισσότερο κατανοήσουμε το πρόβλημα τόσο πιο πολύ θα προσεγγίσουμε την καλύτερη λύση για αυτό. Βέβαια υπάρχει μια αντικειμενική ορθή αντιμετώπιση του προβλήματος, αλλά μια σωστή αιτιολογημένη απάντηση δεν στερείται τίποτα απ’ αυτή.
Συνήθως η πληθυκότητα των δύο αυτών σχέσεων είναι ένα προς πολλά(1--- *), και διαφέρουν ως προς την υλοποίηση τους στην java.

Για την υλοποίηση τους και στις δύο περιπτώσεις μπορούμε να χρησιμοποιήσουμε Vector. Δηλαδή μια δομή που δεδομένων που διατηρεί αντικείμενα της ίδιας κλάσης. Μπορούν να μεγαλώνουν και να μικραίνουν σε μέγεθος ανά πάσα στιγμή. Η κλάση Vector ανήκει στο πακέτο java.util γι’ αυτό και στην αρχή του προγράμματός μας κάνουμε εισαγωγή του πακέτου με την εντολή, import java.util.*; ή import java.util.Vector;

Υλοποίηση Aggregation

Για να μελετήσουμε την περίπτωση αυτή ας πάρουμε ένα παράδειγμα, της τάξης με τους μαθητές της.


Ας δημιουργήσουμε την κλάση μαθητή. Είναι:

public class Pupil {
private String firstname;
private String lastname;
private double age;
public Pupil(String fn, String ln, double a){
this.firstname=fn;
this.lastname=ln;
this.age=a;
}
public String toString(){
return(" "+firstname+" "+lastname+" ");
}
}
Ας δούμε την κλάση τάξη, θα είναι:
public class Room {
private int numroom;
private String nameroom;
static Vector pup;
public Room( String nameroom, int numroom){
this.nameroom=nameroom;
this.numroom=numroom;
Vector pup= new Vector();// υλοποιώ τον Vector μέσα στον κατασκευαστή
}
public void addPupil(Pupil p1){// μέθοδος προσθήκης μαθητή στον vector
pup.add(p1);
}
public String toString(){
return("Η τάξη "+nameroom+numroom+" έχει τον μαθητή ");
}
}


Ας δούμε τώρα την main


public static void main(String[] args) {
Room rm= new Room("A",1);
Pupil pm1=new Pupil("Κώστας","Μαρτάκης",12);
Pupil pm2= new Pupil("Σάκης","Ρουβάς",12);
rm.addPupil(pm1);
rm.addPupil(pm2);
System.out.println(rm);
Iterator it= pup.iterator();//δείκτης στον vector pup
while(it.hasNext()){// ενώσω έχω στοιχεία στον vector
Pupil str=(Pupil)it.next();// παίρνω το επόμενο αντικείμενο Pupil
System.out.println(str);// και το εκτυπώνω όσο ισχύει η while
}
}

Αποτέλεσμα όλων αυτών είναι
run:
Η τάξη A1 έχει τον μαθητή
Κώστας Μαρτάκης
Σάκης Ρουβάς
BUILD SUCCESSFUL (total time: 0 seconds)

Υλοποίηση Composition

Όπως και προηγουμένως έτσι και στην υλοποίηση της composition πραγματοποιείται με την βοήθεια Vector. Δεν θα πρέπει όμως να ξεχνάμε ότι τώρα τα αντικείμενα μας δεν έχουν αυτοτέλεια αλλά συνθέτουν το όλο απερίσπαστα. Υπό αυτή την λογική, είναι κατανοητό ότι η δημιουργία των αντικειμένων μας θα γίνεται εντός του κατασκευαστή του όλου.
Ας δούμε λοιπόν ένα παράδειγμα.
Ένα σχολείο έχει αίθουσες, και είναι λογικό ότι οι αίθουσες αυτές αποκτούν υπόσταση μόνο αν είναι μέρος ενός σχολείου. Θα υλοποιήσουμε αυτήν την σχέση, ξεκινώντας από την κλάση αίθουσες (Room). Θα είναι:

public class Room {
private int numroom;
private String nameroom;
public Room(String nameroom, int numroom){
this.nameroom=nameroom;
this.numroom= numroom;
}
}

Να δούμε τώρα και την κλάση σχολείο,
public class School {
private String nameofschool;
private Vector rooms;
public School (String nameofschool){
this.nameofschool=nameofschool;
rooms=new Vector();//Υλοποίηση του Vector εντός κατασκευαστή
Room r1= new Room("A",1);//Υλοποίηση αιθουσών εντός κατασκευαστή
Room r2= new Room("A",2);//Προσθήκη αιθουσών στον Vector εντός κατασκευαστή
Room r3= new Room("B",1);
Room r4 =new Room("B",2);
rooms.add(r1);//Υλοποίηση αιθουσών εντός κατασκευαστή
rooms.add(r2);
rooms.add(r3);
rooms.add(r4);
}
}


Τώρα θα εμπλουτίσουμε τις κλάσεις με ορισμένες μεθόδους
για την εμφάνιση των αποτελεσμάτων, για την κλάση αίθουσες θα είναι:
public class Room {
private int numroom;
private String nameroom;
public Room(String nameroom, int numroom){
this.nameroom=nameroom;
this.numroom= numroom;
}
public String toString(){
return (" "+nameroom+" "+numroom);
}
}
Και για την κλάση σχολείο είναι :
public class School {
private String nameofschool;
private Vector rooms;
public School (String nameofschool){
this.nameofschool=nameofschool;
rooms=new Vector();
Room r1= new Room("A",1);
Room r2= new Room("A",2);
Room r3= new Room("B",1);
Room r4 =new Room("B",2);
rooms.add(r1);
rooms.add(r2);
rooms.add(r3);
rooms.add(r4);
}
public void printRooms(){
for (Room ro : rooms) {//διαπέρση του Vector
System.out.println(ro);
}
}
public String toString(){
return(" Tο σχολείο "+nameofschool+" έχει τις τάξεις ");
}
}
Στην main θα έχουμε
public static void main(String[] args) {
School sh= new School("1 Λύκειο");
System.out.println(sh);
sh.printRooms();
}
Αποτέλεσμα αυτών :
run:
Το σχολείο 1 Λύκειο έχει τις τάξεις
A 1
A 2
B 1
B 2
BUILD SUCCESSFUL (total time: 0 seconds)


  • Θυμηθείτε ότι στην Aggregation υλοποιώ μέσα στον κατασκευαστή τον Vector αλλά υλοποιώ και μια μέθοδο εκτός κατασκευαστή για να προσθέτω αντικείμενα σε αυτόν. Τα αντικείμενα του, υλοποιούνται στην main.
  •  Αντίθετα στην Composition υλοποιώ μέσα στον κατασκευαστή τον Vector αλλά και τα αντικείμενα του, καθώς και την προσθήκη των αντικειμένων σε αυτόν.
  •  Μια διαπέρση του Vector μπορεί να γίνει είτε με την δημιουργία δείκτη (Iterator)και κλήση της while είτε με την for.
  • Για εκπαιδευτικούς λόγους, το παράδειγμα με την κλήση της while μπήκε στην main και έτσι ο Vector υποχρεώθηκε να γίνει static. Θα μπορούσε να είχε υλοποιηθεί στα πλαίσια μιας μεθόδου, όπως στο δεύτερο παράδειγμα με την for, αποφεύγοντας το χαρακτηρισμό static.
  • Οικειοποιηθείτε έναν από τους δύο τρόπους, όποιος σας είναι πιο κατανοητός, και χρησιμοποιήστε τον σε κάθε πρόγραμμά σας.

Αν σας φάνηκε χρήσιμο το άρθρο αυτό αφήστε τα σχόλιά σας.