Agregação versus composição [fechado]

89

Tive dificuldade em entender a diferença entre composição e agregação em UML. Alguém pode me oferecer uma boa comparação e contraste entre eles? Eu também adoraria aprender a reconhecer a diferença entre eles no código e / ou ver um pequeno exemplo de software / código.

Edit: Parte da razão pela qual pergunto é por causa de uma atividade de documentação reversa que estamos fazendo no trabalho. Nós escrevemos o código, mas precisamos voltar e criar diagramas de classes para o código. Gostaríamos apenas de capturar as associações adequadamente.

Dave
fonte
Por favor, verifique um exemplo baseado em código em: stackoverflow.com/questions/731802/…
Almir Campos
A UML 2.5 esclareceu a diferença. Veja o quadro na pág. 110. Então, estou votando para reabrir isto.
qwerty_so
Não, a UML 2.5 não esclareceu a definição de composição, em vez disso, permaneceu ambígua sobre ela, uma vez que também dizem "Um objeto de parte pode ser removido de um objeto de composição antes que o objeto de composição seja excluído e, portanto, não pode ser excluído como parte de o objeto composto. " Veja minha resposta abaixo ( stackoverflow.com/questions/734891/… ) onde tentei esclarecer o significado de composição. Por favor, vote a favor da minha resposta para mostrar que no SO, a resposta correta vence no final :-) [ou downvote todas as respostas incorretas]
Gerd Wagner

Respostas:

90

A distinção entre agregação e composição depende do contexto.

Veja o exemplo do carro mencionado em outra resposta - sim, é verdade que o escapamento de um carro pode se sustentar "sozinho", então pode não estar em composição com um carro - mas depende da aplicação. Se você criar um aplicativo que realmente precisa lidar com escapamentos de automóveis autônomos (um aplicativo de gerenciamento de oficina de automóveis?), A agregação seria sua escolha. Mas se este for um jogo de corrida simples e o escapamento do carro servir apenas como parte de um carro - bem, a composição seria muito boa.

Tabuleiro de xadrez? Mesmo problema. Uma peça de xadrez não existe sem um tabuleiro de xadrez apenas em certas aplicações. Em outros (como o de um fabricante de brinquedos), uma peça de xadrez certamente não pode ser transformada em um tabuleiro de xadrez.

As coisas ficam ainda piores ao tentar mapear a composição / agregação para sua linguagem de programação favorita. Em alguns idiomas, a diferença pode ser mais fácil de notar ("por referência" vs. "por valor", quando as coisas são simples), mas em outros pode nem existir.

E um último conselho? Não perca muito tempo com esse assunto. Não vale a pena. A distinção é dificilmente útil na prática (mesmo se você tiver uma "composição" completamente clara, você ainda pode querer implementá-la como uma agregação devido a razões técnicas - por exemplo, cache).

Hexágono
fonte
1
Eu disse quadrado de xadrez em vez de peça de xadrez, mas todos os pontos válidos.
David M,
2
Eu definitivamente tenho problemas com a mentalidade "Não vale a pena". Se você não pensar em quem "possui" um objeto e é responsável por sua vida útil, você obterá um código muito ruim relacionado ao objeto CRUD, particularmente limpeza, com ponteiros nulos voando enquanto as hierarquias de objetos são deixadas em mau estado.
Chris Kessel,
9
Sim, você não deve perder muito tempo com este problema: UML é uma linguagem OOA / OOD; Agregação / composição é geralmente uma decisão que é melhor adiada até OOP. Se você tentar colocar muitos detalhes em seus modelos UML, você corre o risco de paralisar a análise.
chimpanzé de
13
1 para "não perca muito tempo com isso". Era isso que eu precisava ouvir!
Ronnie de
8
"não perca muito tempo com isso" Por que os entrevistadores não entendem isso?
titogeo
96

Como um princípio básico: insira a descrição da imagem aqui

class Person {
    private Heart heart;
    private List<Hand> hands;
}

class City {
    private List<Tree> trees;
    private List<Car> cars
}

Na composição (Pessoa, Coração, Mão), "subobjetos" (Coração, Mão) serão destruídos assim que a Pessoa for destruída.

Na agregação (cidade, árvore, carro), os "subobjetos" (árvore, carro) NÃO serão destruídos quando a cidade for destruída.

O resultado final é que a composição enfatiza a existência mútua e, na agregação, essa propriedade NÃO é necessária.

nxhoaf
fonte
1
existência mútua, boa B-)
jxramos
Aprecio seu esforço. Uma explicação muito boa e qualquer leigo pode entender isso.
Ravindran Kanniah
A explicação mais simples e melhor que encontrei.
Akash Raghav
melhor explicação :)
Xiabili
A UML 2.5 esclareceu a diferença. Veja o quadro na pág. 110. Sua resposta está simplesmente errada agora,
qwerty_so
51

Composição e agregação são tipos de associações. Eles estão intimamente relacionados e em termos de programação não parece haver muita diferença entre os dois. Vou tentar explicar a diferença entre esses dois por exemplos de código java

Agregação : O objeto existe fora do outro, é criado fora, por isso é passado como um argumento (por exemplo) para o construtor. Ex: Pessoas - carro. O carro é criado em um contexto diferente e então se torna uma propriedade pessoal.

// code example for Aggregation:
// reference existing HttpListener and RequestProcessor
public class WebServer {
  private HttpListener listener;
  private RequestProcessor processor;
  public WebServer(HttpListener listener, RequestProcessor processor) {
    this.listener = listener;
    this.processor = processor;
  }
}

Composição : O objeto só existe, ou só faz sentido dentro do outro, como parte do outro. Ex: Pessoas - coração. Você não cria um coração e depois o passa para uma pessoa. Em vez disso, o coração é criado quando o humano é criado.

// code example for composition:
// create own HttpListener and RequestProcessor
public class WebServer {
  private HttpListener listener;
  private RequestProcessor processor;
  public WebServer() {
    this.listener = new HttpListener(80);
    this.processor = new RequestProcessor(“/www/root”);
  }
}

Explicado aqui com um exemplo de diferença entre agregação e composição

vsingh
fonte
5
Uma das melhores respostas até agora. Legal :)
Rohit Singh
6
O melhor exemplo de código Java de mostrar quando o objeto pode existir com (composição) ou sem (agregação) outros objetos.
Michał Dobi Dobrzański
por favor, eu quero saber se devemos usar final para composição ou não?
Outreagous ONE
36

A composição implica que os objetos filho compartilham uma vida útil com o pai. A agregação não. Por exemplo, um tabuleiro de xadrez é composto de quadrados de xadrez - os quadrados de xadrez realmente não existem sem o tabuleiro. No entanto, um carro é um agregado de peças - um escapamento de carro ainda é um escapamento de carro se não fizer parte de um carro no momento.

David M
fonte
18

O exemplo que aprendi foi o dedo na mão. Sua mão é composta de dedos. Ele os possui. Se a mão morrer, os dedos morrem. Você não pode "agregar" dedos. Você não pode simplesmente pegar dedos extras e prendê-los e destacá-los de sua mão à vontade.

O valor aqui, do ponto de vista do design, geralmente está relacionado à vida útil do objeto, como disse outro pôster. Digamos que você tenha um cliente e ele tenha uma conta. Essa conta é um objeto "composto" do cliente (pelo menos, na maioria dos contextos em que consigo pensar). Se você excluir o cliente, a conta não terá valor em si mesma, portanto, também será excluída. O inverso costuma ser verdadeiro na criação de objetos. Uma vez que uma conta só tem significado no contexto de um cliente, você faria com que a criação da conta ocorresse como parte da criação do cliente (ou, se preguiçosamente, seria parte de alguma transação do cliente).

É útil no design pensar sobre quais objetos possuem (compõem) outros objetos versus aqueles que apenas fazem referência (agregam) outros objetos. Pode ajudar a determinar onde reside a responsabilidade pela criação / limpeza / atualizações do objeto.

Quanto ao código, geralmente é difícil dizer. Quase tudo no código é uma referência de objeto, portanto, pode não ser óbvio se o objeto referenciado é composto (pertencente) ou agregado.

Chris Kessel
fonte
15

É incrível quanta confusão existe sobre a distinção entre a parte-todo - agregação de conceitos de associação e composição . O principal problema é o mal-entendido generalizado (mesmo entre desenvolvedores de software especializados e entre os autores da UML) de que o conceito de composição implica uma dependência do ciclo de vida entre o todo e suas partes, de forma que as partes não podem existir sem o todo. Mas essa visão ignora o fato de que também há casos de associações parte-todo com partes não compartilháveis, em que as partes podem ser destacadas e sobreviver à destruição do todo.

No documento de especificação UML, a definição do termo "composição" sempre implicou em partes não compartilháveis, mas não ficou claro qual é a característica definidora de "composição" e o que é meramente uma característica opcional. Mesmo na nova versão (a partir de 2015), UML 2.5, após uma tentativa de melhorar a definição do termo "composição", ela permanece ambígua e não fornece qualquer orientação sobre como modelar associações parte-todo com não partes compartilháveis ​​em que as partes podem ser destacadas e sobrevivem à destruição do todo, em oposição ao caso em que as partes não podem ser destacadas e são destruídas juntamente com o todo. Eles dizem

Se um objeto de composição for excluído, todas as suas instâncias de parte que são objetos são excluídas com ele.

Mas ao mesmo tempo eles também dizem

Um objeto de parte pode ser removido de um objeto de composição antes que o objeto de composição seja excluído e, portanto, não pode ser excluído como parte do objeto de composição.

Essa confusão aponta para uma incompletude da definição UML, que não leva em conta as dependências do ciclo de vida entre componentes e compostos. Portanto, é importante compreender como a definição UML pode ser aprimorada pela introdução de um estereótipo UML para composições << inseparáveis >> onde os componentes não podem ser separados de seu composto e, portanto, devem ser destruídos sempre que seu composto for destruído.

1) Composição

Como Martin Fowler explicou , o principal problema para caracterizar a composição é que "um objeto só pode ser parte de uma relação de composição". Isso também é explicado na excelente postagem do blog UML Composition vs Aggregation vs Association de Geert Bellekens. Além dessa característica definidora de uma composição (ter partes exclusivas ou não compartilháveis ), uma composição também pode vir com uma dependência de ciclo de vida entre o composto e seus componentes. Na verdade, existem dois tipos de dependências:

  1. Sempre que um componente deve sempre ser anexado a um composto, ou, em outras palavras, quando ele tem um composto obrigatório , conforme expresso pela multiplicidade "exatamente um" no lado composto da linha de composição, então ele deve ser reutilizado em (ou reconectado a) outro composto, ou destruído, quando seu composto atual é destruído. Isso é exemplificado pela composição entre Persone Heart, mostrada no diagrama abaixo. Um coração é destruído ou transplantado para outra pessoa, quando seu dono morre.
  2. Sempre que um componente não puder ser separado de seu composto, ou seja, quando for inseparável , então, e somente então, o componente deverá ser destruído, quando seu composto for destruído. Um exemplo de tal composição com partes inseparáveis ​​é a composição entre Persone Brain.

insira a descrição da imagem aqui

Em resumo, as dependências do ciclo de vida só se aplicam a casos específicos de composição, mas não em geral; portanto, não são uma característica definidora.

A especificação UML afirma: "Uma parte pode ser removida de uma instância composta antes que a instância composta seja excluída e, portanto, não pode ser excluída como parte da instância composta." No exemplo de uma composição Car- Engine, conforme mostrado no diagrama a seguir, é claro que o motor pode ser retirado do carro antes que o carro seja destruído, caso em que o motor não é destruído e pode ser reutilizado. Isso está implícito no zero ou uma multiplicidade no lado composto da linha de composição.

insira a descrição da imagem aqui

A multiplicidade da extremidade de associação de uma composição no lado do composto é 1 ou 0..1, dependendo do fato de os componentes terem um composto obrigatório (devem ser anexados a um composto) ou não. Se os componentes forem inseparáveis , isso significa que eles têm um composto obrigatório.

2) Agregação

Uma agregação é outra forma especial de associação com o significado pretendido de um relacionamento parte-todo, onde as partes de um todo podem ser compartilhadas com outros todos. Por exemplo, podemos modelar uma agregação entre as classes DegreePrograme Course, conforme mostrado no diagrama a seguir, uma vez que um curso faz parte de um programa de graduação e um curso pode ser compartilhado entre dois ou mais programas de graduação (por exemplo, um diploma de engenharia pode compartilhar um C curso de programação com graduação em ciência da computação).

insira a descrição da imagem aqui

No entanto, o conceito de uma agregação com partes compartilháveis não significa muito, realmente, por isso não tem implicações na implementação e muitos desenvolvedores, portanto, preferem não usar o diamante branco em seus diagramas de classe, mas apenas modelar uma associação simples em vez de. A especificação UML diz: "A semântica precisa da agregação compartilhada varia por área de aplicativo e modelador".

A multiplicidade da extremidade da associação de uma agregação no lado inteiro pode ser qualquer número (*) porque uma parte pode pertencer a, ou ser compartilhada entre, qualquer número de todos.

Gerd Wagner
fonte
2
A composição não está estritamente relacionada ao ciclo de vida, mas, na maioria dos problemas do mundo real, o ciclo de vida é o principal motivador para decidir se você compõe ou agrega. Eu evitei minha resposta, dizendo que o ciclo de vida está "frequentemente" relacionado, em vez de sempre. É bom notar que o ciclo de vida não é necessário, mas afirmar que a visão é um "problema principal" e errado (em uma bela fonte em negrito) parece-me inútil e impede de apontar as considerações práticas de uso.
Chris Kessel
Eu discordo fortemente. As considerações do ciclo de vida não podem ser um "motivador primário para decidir se você comporá ou agregará", uma vez que você as tem em muitos casos de associações independentemente do fato se representarem qualquer tipo de relação parte-todo (agregação ou composição). Sempre que uma associação tem um final com uma multiplicidade de limite inferior maior que 0, correspondendo a uma propriedade de referência obrigatória, você obterá uma dependência de ciclo de vida.
Gerd Wagner de
9

Em termos de código, a composição geralmente sugere que o objeto que o contém é responsável por criar instâncias do componente *, e o objeto que o contém mantém as únicas referências de longa duração a ele. Portanto, se o objeto pai for desreferenciado e coletado como lixo, o filho também será.

então este código ...

Class Order
   private Collection<LineItem> items;
   ...
   void addOrderLine(Item sku, int quantity){
         items.add(new LineItem(sku, quantity));
   }
}

sugere que LineItem é um componente de Order - LineItems não existe fora do pedido que o contém. Mas os objetos Item não são construídos no pedido - eles são passados ​​conforme necessário e continuam a existir, mesmo se a loja não tiver pedidos. então eles estão associados, em vez de componentes.

* nb o contêiner é responsável por instanciar o componente, mas ele pode não chamar o próprio new ... () - sendo este java, geralmente há uma fábrica ou duas para passar primeiro!

Chris May
fonte
0

As ilustrações conceituais fornecidas em outras respostas são úteis, mas gostaria de compartilhar outro ponto que considerei útil.

Eu obtive algumas milhas de UML para geração de código, para código-fonte ou DDL para banco de dados relacional. Lá, usei composição para indicar que uma tabela tem uma chave estrangeira não anulável (no banco de dados) e um objeto "pai" não anulável (e freqüentemente "final") em meu código. Eu uso a agregação onde pretendo que um registro ou objeto possa existir como um "órfão", não anexado a nenhum objeto pai ou ser "adotado" por um objeto pai diferente.

Em outras palavras, usei a notação de composição como um atalho para sugerir algumas restrições extras que podem ser necessárias ao escrever o código para o modelo.

Erickson
fonte
0

O exemplo que eu gosto: Composição: Água é parte de um Lago. (O lago é uma composição de água.) Agregação: o lago tem patos e peixes (o lago agrega patos e peixes)

Como você pode ver, coloquei "parte de" em negrito e "tem", pois essas duas frases podem apontar tipicamente o tipo de conexão que existe entre as classes.

Mas, como apontado por outros, muitas vezes se a conexão é uma composição ou uma agregação depende do aplicativo.

Raj Rao
fonte
Mas parte-de e tem termos confunde às vezes. Por exemplo, uma classe Person "tem" um nome, então mostra como Person tem uma relação de agregação com o nome. Na verdade, é uma relação de composição. Por quê? Quando o objeto Person destrói, o nome também deve ser destruído. E o termo "nome é uma parte da pessoa" não parece natural.
Asif Shahzad
0

É tão difícil fazer uma diferença entre relação agregada e relação composta, mas vou dar alguns exemplos, temos uma casa e quartos, aqui temos uma relação composta, quarto é parte da casa e a vida no quarto começou com a vida da casa e A vontade termina quando a vida da casa acabar, o quarto faz parte da casa, falamos de composição, como país e capital, livro e páginas. Por exemplo de relação agregada, pegue equipe e jogadores, o jogador pode existir sem equipe e a equipe é um grupo de jogadores, e a vida do jogador pode começar antes da vida da equipe, se falarmos de programação, podemos criar jogadores e depois criaremos equipe, mas para composição não, nós criamos cômodos dentro de casa. Composição ----> composto | composição. Agregação -------> grupo | elemento

ler
fonte
0

Vamos definir os termos. A agregação é um metatermo no padrão UML e significa AMBOS a composição e a agregação compartilhada, simplesmente denominada compartilhada . Muitas vezes é denominado incorretamente de "agregação". É RUIM, pois a composição também é uma agregação. Pelo que entendi, você quer dizer "compartilhado".

Mais além do padrão UML:

composto - Indica que a propriedade é agregada de forma composta, ou seja, o objeto composto é responsável pela existência e armazenamento dos objetos compostos (partes).

Então, a associação Universidade para cátedras é uma composição, porque cátedra não existe fora da universidade (IMHO)

A semântica precisa de agregação compartilhada varia por área de aplicativo e modelador.

Ou seja, todas as outras associações podem ser desenhadas como agregações compartilhadas, se você estiver apenas seguindo alguns princípios seus ou de outra pessoa. Veja também aqui .

Gangnus
fonte
0

Considere partes do corpo humano como rim, fígado, cérebro. Se tentarmos mapear o conceito de composição e agregação aqui, seria como:

Antes do advento do transplante de partes do corpo, como o do rim e o do fígado, essas duas partes do corpo estavam em composição com o corpo humano e não podem existir isoladas com o corpo humano.

Mas após o advento do transplante de parte do corpo, elas podem ser transplantadas em outro corpo humano, então essas partes estão agregadas ao corpo humano, pois sua existência isolada com o corpo humano é possível agora.

Azfar Niaz
fonte