Comprendere meglio la composizione UML

5

La differenza tra Composizione e Aggregazione in UML (e talvolta anche nella programmazione) è che con Composition, la durata degli oggetti che compongono il composito (ad esempio un motore e un volante in un'auto) dipende dall'oggetto composito. Mentre con Aggregation, la durata degli oggetti che compongono il composito è indipendente dal composito.

Tuttavia non sono sicuro di qualcosa relativo alla composizione in UML.

Dire che ClassA è composto da un oggetto di ClassB:

class ClassA{
    ClassB bInstance;
    public ClassA(){
        bInstance = new ClassB();
    }
}

Questo è un esempio di composizione, perché bInstance dipende dalla durata del suo oggetto che lo racchiude.

Tuttavia, per quanto riguarda la notazione UML - non sono sicuro di voler annotare la relazione tra ClassA e ClassB con un diamante pieno (composizione) o un diamante bianco (aggregazione).

Questo perché mentre la vita di alcune % istanze diClassB dipende da% istanze diClassA - potrebbero esserci% istanze diClassB in qualsiasi altro punto del programma - non solo all'interno di% istanze diClassA .

La domanda è: se alcuni oggetti ClassB sono composti con oggetti ClassA (e quindi dipendono dalla durata degli oggetti ClassA) , ma alcuni non sono - la relazione tra le due classi in UML potrebbe essere un'aggregazione o una relazione di composizione ??

    
posta Aviv Cohn 26.05.2014 - 19:49
fonte

6 risposte

0

Risposta breve: UML non si preoccupa delle classi interne. Le classi interne sono una funzionalità in Java e in altre lingue, ma non tutte le supportano. In effetti, le classi interne sono di solito un dettaglio di implementazione che molto spesso non viene mostrato nei diagrammi UML.

Ora, se il codice di esempio è Java (ma potrebbe essere qualsiasi altra cosa) direi che potrebbe (1) essere l'aggregazione, o neanche ... o forse la composizione

Come esempio di aggregazione, potresti avere una classe di raccolta, in cui ogni elemento è memorizzato in una classe interna. Un esempio di questo potrebbe essere Classe HashMap.Entry in Java, ma è statica e protetta da pacchetti, poiché viene utilizzata da altre classi in java.util.

E come un esempio di nessuno sarebbe se si desidera avere una classe helper, ma non si vuole creare una classe di livello superiore o una classe interna anonima. Ad esempio, se desideri creare un'istanza di un Comparatore personalizzato.

Ultimo ma non meno importante, potrebbe essere un esempio di cattiva composizione.

(1) Dico che potrebbe essere, perché ci sono molti esempi veramente cattivi o composizione e aggregazione nella maggior parte delle basi di codice su cui ho lavorato.

    
risposta data 26.05.2014 - 23:59
fonte
0

Credo che tu abbia risposto alla tua domanda quando hai detto "la vita degli oggetti che compongono il composito (ad esempio un motore e un volante in un'automobile) dipende dall'oggetto composito". Nell'esempio di codice, l'oggetto B cesserà di esistere quando l'oggetto A è scomparso. D'altra parte,

class ClassA{
   ClassB bInstance;
  public ClassA(ClassB classB){
    bInstance = classB;
  }
}

diventerebbe un aggregato nel tuo UML poiché l'oggetto B può esistere indipendentemente dall'oggetto A.

EDIT (dopo l'aggiornamento) Ho provato ad immaginare un'istanza in cui la Classe B dipenderebbe dalla Classe A ed ecco quello che mi viene in mente:

class ClassA{
   bool bDependsOnA = // true or false based on some logic
   ClassB bInstance;
   public ClassA(){
     if(bDependsOnA){
        bInstance = new ClassB(this);
      }else{
        bInstance = new ClassB();
    }
  }
}

class ClassB{
   ClassA aInstance;
  public ClassB()
  { 
     aInstance = null;
  }
  public ClassB(ClassA classA ){
    aInstance = classA;
  }
}

La Classe B è un composto di classe A, ClassB ha un'associazione debole con la Classe A. Un articolo interessante che ho trovato, mentre pensavo alla tua domanda ( link )

A proposito, per quanto UML sia, non è perfetto. L'aggregazione e la composizione andavano avanti da molto tempo. A volte, non è chiaro cosa sia cosa. Personalmente, ho scoperto che quando sono bloccato a cercare di decidere quale sia, significa che il mio design è troppo complesso e potrebbe essere semplificato:)

    
risposta data 27.05.2014 - 00:54
fonte
0

Ecco un altro modo per vederlo:

Come @rommik ha evidenziato con il suo esempio, potresti anche passare l'oggetto B come argomento del costruttore, disaccoppiando così il suo ciclo di vita da A . Ora dimentica il diagramma UML corrispondente e pensa prima alle tue classi. Hai (almeno queste) due opzioni:

class A { ... public A(B bInstance) { ...} }

o

class A { B bInstance = new B(); ... }

Ci sono buone ragioni per utilizzare entrambi, a seconda delle circostanze, e si adattano naturalmente alla semantica di aggregazione e di composizione di UML, rispettivamente.

D'altra parte, la tua modifica propone che la classe A abbia alcune istanze , dove la durata dell'oggetto B dipende dall'istanza A e altre istanze , dove non lo fa.

Lascia fuori UML e guardalo semplicemente dal punto di vista del design generale. La tua classe A ha improvvisamente ottenuto molto più complicato. Naturalmente, non c'è da meravigliarsi se si riscontrano problemi nel cercare di descriverlo in un diagramma UML. Diamine, avresti anche problemi a spiegare qualcun altro che cosa fa A : "Ottiene B oggetti e fa questo e quello con loro .. oh tranne quando crea il proprio B oggetti ..". Confrontalo per spiegare una delle due varianti chiare sopra.

In sintesi, il fatto che tu abbia due modi semanticamente diversi di modellare il tuo progetto in UML non è né un problema di UML stesso, né la tua comprensione di esso. È semplicemente un puntatore per ricordarti che il tuo design di classe è ambiguo riguardo alla sua semantica.

    
risposta data 27.05.2014 - 07:15
fonte
0

La tua composizione ha lo scopo di modellare situazioni in cui un oggetto fa parte di un altro oggetto nel modo in cui una determinata vite può far parte di un camion? Non tutte le viti fanno parte di un camion. Se è così non dovresti usare la relazione di composizione. UML2 include un'altra nozione di un oggetto composito che ha parti che costituiscono un intero.

Se la classe A è un'aggregazione composita di classe B , allora ogni istanza di B deve avere un istanza correlata di A che lo aggrega. Non quello che vuoi.

Nella situazione che descrivi, le istanze della classe A sono oggetti compositi che contengono istanze di classe B come parti. Ciò non esclude la possibilità di istanze di B che non fanno parte degli oggetti A . La relazione tra A e B non è né aggregazione né composizione. La terminologia (rapporto di composizione vs struttura / parte composita) è confusa, ma siamo bloccati con esso.

    
risposta data 21.11.2014 - 02:11
fonte
0

La questione se la relazione tra ClassA e ClassB sia composta non dipende dal fatto che ci siano anche istanze di ClassB che non fanno parte di nessun ClassA . Nel tuo esempio, fino a quando nessun riferimento al% interno interno% istanza (quello contenuto nella tua variabile di istanza ClassB ) può mai sfuggire l'istanza contenente bInstance (che potrebbe accadere se hai un getter pubblico per ClassA , ad esempio), stai perfettamente modellando questo come una relazione composita.

Nel tuo modello UML, è la molteplicità del finale contenitore che determina se tutte le bInstance istanze dovrebbero essere parte di qualche ClassB . La molteplicità della fine del contenitore non può mai essere diversa da ClassA o [0..1] in primo luogo, naturalmente (altrimenti ciò violerebbe il principio che un oggetto può al massimo essere parte di una singola composizione); se è [1..1] stai dicendo che ci possono essere anche [0..1] -instances non parte di ClassB ; se è ClassA , questo non è il caso.

Vedi anche link per una discussione illuminante.

    
risposta data 18.07.2016 - 17:29
fonte
0

È composizione perché stai modellando la relazione tra

le classi A e B. NON le relazioni tra la Classe B e il resto di

il programma.

La classe C utilizza istanze di classe B nello schema sopra, ma lo fa

non necessariamente termina la vita delle istanze di Classe B. Sono in grado

per esistere al di fuori della classe C a causa della funzione getB (). Un esempio

potrebbe essere un album di canzoni. Puoi spostare i brani fuori dall'album in

un altro poi distrugge il vecchio album.

Al contrario, la Classe A è composta da un'istanza di Classe B perché non c'è modo per

le istanze di Classe B possono esistere al di fuori della Classe A. Un esempio è la vita

di una persona e dei suoi segreti. Ogni persona ha segreti. Nessuno lo sa

su questi segreti e quando quella persona muore, i loro segreti muoiono con

li.

    
risposta data 03.08.2018 - 05:33
fonte

Leggi altre domande sui tag