A che cosa servono Associazione, Aggregazione e Composizione?


20

Ho analizzato molte teorie su ciò che è l'incapsulamento e le tre tecniche di attuazione, che sono Associazione, Aggregazione e Composizione.

Quello che ho trovato è :

incapsulamento

L'incapsulamento è la tecnica per rendere privati ​​i campi in una classe e fornire accesso ai campi con metodi pubblici. Se un campo viene dichiarato privato, non può accedervi da nessuno al di fuori della classe, nascondendo così i campi all'interno della classe. Per questo motivo, l'incapsulamento è anche indicato come nascondere i dati.

L'incapsulamento può essere descritto come una barriera protettiva che impedisce al codice e ai dati di accedere casualmente ad altri codici definiti al di fuori della classe. L'accesso ai dati e al codice è strettamente controllato da un'interfaccia.

Il principale vantaggio dell'incapsulamento è la possibilità di modificare il nostro codice implementato senza rompere il codice di altri che usano il nostro codice. Con questa funzione l'incapsulamento fornisce manutenibilità, flessibilità ed estensibilità al nostro codice.

Associazione

L'associazione è una relazione in cui tutti gli oggetti hanno il proprio ciclo di vita e non esiste un proprietario. Facciamo un esempio di insegnante e studente. Più studenti possono associarsi con un singolo insegnante e un singolo studente può associarsi con più insegnanti, ma non esiste alcuna proprietà tra gli oggetti ed entrambi hanno il proprio ciclo di vita. Entrambi possono creare ed eliminare in modo indipendente.

Aggregazione

L'aggregazione è una forma specializzata di associazione in cui tutti gli oggetti hanno il proprio ciclo di vita, ma esiste la proprietà e un oggetto figlio non può appartenere a un altro oggetto padre. Facciamo un esempio di dipartimento e insegnante. Un singolo insegnante non può appartenere a più dipartimenti, ma se eliminiamo il dipartimento l'oggetto insegnante non verrà distrutto. Possiamo pensarlo come una relazione "ha-a".

Composizione

La composizione è di nuovo una forma specializzata di aggregazione e possiamo definirla una relazione di "morte". È un tipo forte di aggregazione. L'oggetto figlio non ha il suo ciclo di vita e se l'oggetto padre elimina tutti gli oggetti figlio verranno eliminati. Riprendiamo un esempio di relazione tra casa e stanze. La casa può contenere più stanze ma non esiste una vita indipendente di una stanza e ogni stanza non può appartenere a due case diverse. Se cancelliamo la casa, la stanza verrà automaticamente cancellata.

La domanda è:

Ora questi sono tutti esempi del mondo reale. Sto cercando una descrizione su come utilizzare queste tecniche nel codice di classe reale. Voglio dire qual è il punto per usare tre diverse tecniche per l'incapsulamento , come queste tecniche potrebbero essere implementate e come scegliere quale tecnica è applicabile al momento.


1
Si noti che aggregazione, composizione e associazione non sono tecniche per implementare l'incapsulamento. Un incapsulamento può anche esistere anche se esiste solo una classe / oggetto. L'incapsulamento è solo una funzione essenziale in Orientamento oggetto per nascondere i dati dell'oggetto.
Maxood,

1
" Davvero un singolo insegnante NON può appartenere a più dipartimenti"? Non hai notato che la tua risorsa ha modificato il contenuto?
KNU

Sono riuscito a utilizzare Composizione per identificare le radici aggregate DDD e le loro entità durante la progettazione guidata dal dominio. Un nuovo uso per una vecchia convenzione.
Jonn

Risposte:


12

La distinzione tra associazione, aggregazione e composizione mentre la descrivi è un'eredità che risale ai vecchi tempi della gestione manuale della memoria. Ad esempio in C ++ la memoria utilizzata dagli oggetti deve essere rilasciata manualmente ed è quindi fondamentale progettare attentamente il ciclo di vita degli oggetti composti. Mentre la distinzione tra aggregazione e composizione viene ancora insegnata da molti libri di testo, è essenzialmente irrilevante quando si programma in ambienti con gestione automatica della memoria. Se hai la garbage collection, tutti sono solo composizione, punto.

L'incapsulamento invece è un principio molto più generale di quello che descrivi. È innanzitutto l'idea di raggruppare i dati e le funzioni che operano su questi dati in un modulo. Un modo per implementarlo è mantenere lo stato del modulo privato ed esporre le modifiche a tale stato attraverso i servizi pubblici. Quindi il client non può accedere allo stato da solo ma deve comunicare al modulo la propria intenzione inviando messaggi. Quindi l'incapsulamento non si limita agli oggetti ma si applica anche ai servizi. In realtà, un modo di guardare gli oggetti è guardarli come servizi.

Ecco un esempio di incapsulamento

public class Counter {
    private int n = 0;
    public int inc() { return n++; }
}

o lo stesso usando le funzioni lambda

var counter = (function() {
    var n = 0;
    var inc = function() { return n++; }
    return inc;
})();

In entrambi i casi i dati, ovvero la variabile n, sono raggruppati insieme alla funzione incche vi opera. E non vi è alcun modo in cui qualsiasi altra funzione possa mai accedere n, quindi abbiamo un modulo incapsulato che fornisce il conteggio come servizio.

NB: esporre tutto lo stato interno di un oggetto attraverso gli accessori è in realtà una violazione dell'incapsulamento. Purtroppo, è una violazione così comune che molti la confonderanno con un buon design orientato agli oggetti.


2
La gestione automatica della memoria non ha nulla a che fare con le relazioni tra oggetti. Un diagramma a oggetti stesso indica al programmatore come codificare le classi, le loro interfacce e i loro metodi secondo i requisiti del sistema in esame.
Maxood,

2
C'è anche una considerazione al di fuori della memoria. Nella progettazione dei dati o forse nella serializzazione. In composizione, potrebbe essere necessario avere vincoli di chiave esterna diversi in un RDBMS o modificare il modo in cui si gestisce la serializzazione di un oggetto se ha figli compositi rispetto a figli aggregati o oggetti associati.
Chris,

8

L'incapsulamento è la tecnica per rendere privati ​​i campi in una classe e fornire accesso ai campi con metodi pubblici. Se un campo viene dichiarato privato, non può accedervi da nessuno al di fuori della classe, nascondendo così i campi all'interno della classe. Per questo motivo, l'incapsulamento è anche indicato come nascondere i dati.

    public class Test{

    private String name;

       private int age;

       public int getAge(){
          return age;
       }

       public String getName(){
          return name;
       }
    }

Fare riferimento a questa domanda anche .

L'associazione indica la relazione tra oggetti. ad es .: il computer utilizza la tastiera come dispositivo di input.

Un'associazione viene utilizzata quando un oggetto desidera che un altro oggetto esegua un servizio per esso.

L'aggregazione è un caso speciale di associazione. Un'associazione direzionale tra oggetti. Quando un oggetto "ha-a" un altro oggetto, allora hai un'aggregazione tra di loro.

es: Room ha un tavolo, ma il tavolo può esistere senza room.

    class Room {

      private Table table;

      void setTable(Table table) {
        this.table = table;
      }

    }

La composizione è un caso speciale di aggregazione. La composizione è più restrittiva. Quando c'è una composizione tra due oggetti, l'oggetto composto non può esistere senza l'altro oggetto. Questa restrizione non è presente in aggregazione. es: stanze in una casa, che non possono esistere dopo la vita della casa.

    class House {

      private  Room room;

      House(Room roomSpecs) {
        room = new Room(roomSpecs);
      }

    }

La composizione è una tecnica di progettazione per implementare una relazione has-in in classi, tramite Ereditarietà o Composizione oggetto per il riutilizzo del codice.

Una delle migliori pratiche nella programmazione Java è usare la composizione sull'ereditarietà


come risponde alla domanda posta?
moscerino del

1

L'uso di queste tecniche di solito porta a pratiche di progettazione come SOLID o vari modelli di progettazione .

Il punto di usare schemi, pratiche e simili è descrivere una soluzione a un problema specifico che sia anche mantenibile ed estendibile. Devi semplicemente avere abbastanza esperienza per dire dove usare quale modello o tecnica.


1

Sinceramente sento che queste nozioni insegnate in ambito accademico hanno la loro importanza nei contesti dell'orientamento agli oggetti e del design di classe. Questi concetti ci aiutano molto quando si tratta di modellare un sistema da zero. Associazione, Aggregazione e Composizione appartengono esclusivamente al diagramma di classe di UML e sono completamente indipendenti dai vincoli tecnologici come i problemi di memoria.

Inoltre, devi anche considerare il livello superiore o gli obiettivi di business del sistema che stai modellando. Abbiamo in considerazione oggetti come House and Room nel nostro sistema, ma non possiamo essere strettamente correlati (tramite la composizione). Ad esempio, se sto modellando un sistema immobiliare, allora dovrei sapere quale stanza appartiene a quale casa. Ma lascia che stia modellando un sistema di rilevamento o censimento in cui voglio sapere quante persone vivono in ogni stanza della casa in una determinata area, quindi non ho bisogno di mettere in relazione una stanza con una casa tramite la composizione.

Un altro esempio potrebbe essere un frutteto e un certo tipo di frutta. Diciamo che posso considerare un frutteto solo quando ho alberi di mele piantati al suo interno. La linea di fondo è che i requisiti dell'intero sistema contano molto.

L'incapsulamento è uno dei pilastri del design orientato agli oggetti. Devi raggruppare i tuoi dati e le operazioni che eseguirai sui tuoi dati. inoltre devi nascondere alcuni attributi del tuo oggetto dal mondo esterno per consentire a quell'oggetto di sopravvivere in uno stato valido. Quando 2 oggetti interagiscono, devono interagire tra loro tramite un'interfaccia. Ed è ciò che garantisce l'incapsulamento quando progettiamo il nostro sistema OO.

Ecco come questi concetti vengono applicati al codice:

ASSOCIAZIONE: L' associazione indica la relazione tra oggetti. Permette al programmatore di sapere quali metodi scrivere nelle proprie classi per farli interagire tra loro. Puoi trovare diversi esempi di diagrammi di codice e di classe per comprendere l'associazione. Nel tuo esempio di Teach and Student, esiste una relazione di insegnamento e insegnamento da . Quindi scriverai semplicemente una serie di metodi (tecnicamente chiamati interfaccia) attraverso i quali puoi conoscere quale studente ha quali insegnanti e quale insegnante ha quali studenti. L'associazione consente inoltre al modellatore di sistema di aiutare il progettista del database in merito agli attributi e ai campi che devono essere conservati nel database.

COMPOSIZIONE: Se un oggetto è parte integrante di un altro oggetto, allora potrei dover indicare questa relazione nel costruttore dell'altro oggetto. Ad esempio, nel tuo scenario di Case e Stanze possiamo scrivere il seguente codice nel caso in cui vogliamo sapere quale camera appartiene a quale tipo di casa.

class House{
          string _HouseType;   
     public:    
    void setHouseType(string house_type)
     {
        this. _HouseType = house_type;
     } 

     string getHouseType()
    {
       return _HouseType;
    }
};



 House HouseObject = new House();


class Room{

 public: 
 Room(string HouseType) {
       this._HouseType = HouseObject.getHouseType();  //as in my system a room cannot exist without a house

 } 

};

Durante la chiamata dei distruttori dell'oggetto, il programmatore assicurerà anche che venga richiamato anche il distruttore dell'altro oggetto. Questo è cruciale.

AGGREGAZIONE: Diciamo che se la relazione tra gli oggetti è debole, allora per il programmatore significherebbe usare una variabile di istanza invece di indicare la relazione. E quindi scrivi una funzione mutatore (setter) per fornire valore a quell'oggetto da un altro.

class Department{

 string dept_name;

public:
   void setDeptName(string name)
   {
        this.dept_name=name;
   }

   string getDeptName()
   {
        return dept_name; 
   }

};



 Department DepartmentObject = new Department();

class Teacher{

 string dept_name;

public:

  setDeptName(string name)
  {
     this.dept_name = DepartmentObject.getDeptName();  //You only need to invoje this method when needed (aggregation)
  }
}

};

1

OK, associamolo ad alcune proprietà fondamentali piuttosto che a concetti astratti che hanno senso solo quando capisci cosa significano. Come alcuni commentatori, non sono d'accordo con la risposta accettata, dico che si tratta di concetti indipendenti dalla gestione della memoria.

incapsulamento

Vuoi nascondere la complessità al cliente, pubblicando solo le cose che contano dal punto di vista del cliente, rendendo le cose più facili per il cliente. Come bonus hai la certezza che nulla può interferire con il codice incapsulato. Finché rispetti l'interfaccia e la funzionalità, puoi rielaborare le cose e stare certo che non romperai nulla. La dipendenza è solo sull'interfaccia pubblicata.

L'incapsulamento è uno dei pilastri principali dell'orientamento agli oggetti. Non è un modello, è un principio e può applicarsi sia alla logica che ai dati. In primo luogo è solo un vantaggio fondamentale dell'utilizzo delle classi, non qualcosa che vedresti esplicitamente dichiarato in un diagramma o in un documento di progettazione.

Associazione

Questo è un concetto molto ampio che sostanzialmente descrive solo una dipendenza tra oggetti. Un oggetto è a conoscenza dell'esistenza di un altro oggetto e ad un certo punto può usare la sua funzionalità. In un diagramma l'associazione avviserebbe che esiste una dipendenza e che la modifica di un oggetto può influire sull'altro. Non è una tecnica da applicare quando hai qualche problema da risolvere, è più simile a un fatto della vita di cui dovresti essere consapevole quando è lì. È una relazione. Come una fattura con una proprietà Ordini. Sia Order che Invoice hanno il loro ciclo di vita. Uno riguarda i beni e l'altro riguarda i pagamenti, il che li rende sostanzialmente indipendenti, ma è importante sapere per quali beni vengono pagati.

Contenimento

Sto aggiungendo questo perché appartiene alla serie e renderà l'aggregazione più significativa. Non sento più il termine usato in un contesto SE ma penso che sia ancora utile. Il contenimento implica l'incapsulamento ma riguarda rigorosamente le istanze di oggetto private alla classe contenente. La funzionalità degli oggetti contenuti viene esposta selettivamente tramite interfacce pubbliche. La classe contenente controlla il ciclo di vita degli oggetti controllati. Lo usi quando hai bisogno di alcune funzionalità di una classe esistente per rendere funzionale la classe contenente. Questo potrebbe essere un parser XML e il client della classe contenitore potrebbe non vedere o conoscere mai nulla correlato a XML. Come metafora, pensa all'oggetto contenuto come un lavoratore del back office. I clienti non incontrano mai queste persone, tuttavia sono necessari per fornire il servizio.

Aggregazione

È molto simile al contenimento, tranne per il controllo del ciclo di vita e la visibilità degli oggetti aggregati. Gli oggetti aggregati sono già disponibili in un contesto diverso e sono gestiti da un'entità diversa. L'aggregatore offre semplicemente una facciata, un portale per gli oggetti aggregati. Quando il client indirizza l'aggregato, ottiene l'interfaccia dell'oggetto aggregato stesso, non un wrapper attorno ad esso. Il punto dell'aggregato sta offrendo un raggruppamento logico di cose. Pensa a un punto di accesso ai servizi o ad altri oggetti wrapper.

Composizione

Mi sembra che questo sia il termine più contemporaneo per contenimento, forse perché è stato coniato in un libro popolare di origine relativamente recente. Laddove il contenimento si concentra sugli aspetti tecnici delle relazioni oggettuali, la composizione viene generalmente utilizzata nel contesto delle decisioni di progettazione, in particolare come alternativa più flessibile per l'eredità.

Non dice molto sulla natura delle relazioni con gli oggetti o della proprietà, indica semplicemente che la funzionalità viene implementata combinando la funzionalità delle classi esistenti. Pertanto, direi che non appartiene a questa serie perché non dice nulla sugli aspetti tecnici di un'implementazione in cui gli altri lo fanno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.