Agregação versus Composição

Eu 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 eu pergunto é por causa de uma atividade de documentação inversa que estamos fazendo no trabalho. Nós escrevemos o código, mas precisamos voltar e criar diagramas de classs para o código. Nós gostaríamos apenas de capturar as associações corretamente.

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

Pegue o exemplo do carro mencionado em outra resposta – sim, é verdade que a exaustão de um carro pode ficar “sozinha”, por isso pode não estar em composição com um carro -, mas isso depende da aplicação. Se você construir um aplicativo que realmente tenha que lidar com exaustões de carros independentes (um aplicativo de gerenciamento de oficina de carros?), A agregação seria a sua escolha. Mas se este é um jogo de corrida simples e o escape do carro só serve 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 composta em um tabuleiro de xadrez.

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

E uma última palavra de conselho? Não perca muito tempo com esse problema. Não vale a pena. A distinção é dificilmente útil na prática (mesmo que você tenha uma “composição” completamente clara, você ainda pode querer implementá-la como uma agregação devido a razões técnicas – por exemplo, caching).

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

class Person { private Heart heart; private List hands; } class City { private List trees; private List cars } 

Na composição (Pessoa, Coração, Mão), “sub objects” (Coração, Mão) serão destruídos assim que a Pessoa for destruída.

Em agregação (Cidade, Árvore, Carro) “sub objects” (Árvore, Carro) NÃO serão destruídos quando Cidade for destruída.

A linha inferior é, a composição enfatiza a existência mútua e, em agregação, essa propriedade NÃO é necessária.

Composição implica que os objects filhos compartilham uma vida útil com o pai. 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 é uma agregação de peças – um escape de carro ainda é um escape de carro se não for parte de um carro no momento.

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. Vou tentar explicar a diferença entre esses dois exemplos de código java

Agregação : o object existe fora do outro, é criado fora, então é passado como um argumento (por exemplo) para o construtor. Ex: Pessoas – carro. O carro é criado em um contexto diferente e depois 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 object 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 passa para uma pessoa.

 // 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 Diferença entre agregação e composição

O exemplo que aprendi foram os dedos da mão. Sua mão é composta de dedos. É dono deles. Se a mão morre, os dedos morrem. Você não pode “agregar” os dedos. Você não pode simplesmente pegar os dedos extras e prendê-los e retirá-los da sua mão à vontade.

O valor aqui, do ponto de vista do design, é frequentemente relacionado à vida útil do object como outro pôster disse. Digamos que você tenha um cliente e eles tenham uma conta. Essa conta é um object “composto” do cliente (pelo menos, na maioria dos contextos, posso pensar). Se você excluir o cliente, a conta não terá valor próprio, portanto, também será excluída. O inverso geralmente é verdadeiro na criação de objects. Uma vez que uma conta só tem significado no contexto de um cliente, você teria criação de conta ocorrer como parte da criação do cliente (ou, se você fizer isso preguiçosamente, seria parte de alguma transação do cliente).

É útil no design pensar sobre quais objects possuem (compor) outros objects versus aqueles que apenas fazem referência (agregam) outros objects. Ele pode ajudar a determinar onde está a responsabilidade pela criação / limpeza / atualização de objects.

Tanto quanto no código, muitas vezes é difícil dizer. Quase tudo em código é uma referência de object, portanto, pode não ser óbvio se o object referenciado é composto (próprio) ou agregado.

É incrível a quantidade de confusão existente sobre a distinção entre a agregação e composição dos conceitos de parte-todoassociação . O principal problema é o mal-entendido generalizado (mesmo entre desenvolvedores de software especialistas 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 modo que as partes não possam existir sem o todo. Mas esse ponto de vista ignora o fato de que também existem casos de associações de partes inteiras com partes não compartilháveis, nas quais as partes podem ser separadas e sobreviver à destruição do todo.

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

Se um object composto for excluído, todas as suas instâncias de parte que são objects serão excluídas com ele.

Mas ao mesmo tempo eles também dizem

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

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

1) Composição

Como Martin Fowler explicou , a questão principal para caracterizar a composição é que “um object só pode fazer parte de uma relação de composição”. Isso também é explicado no excelente post 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 do ciclo de vida entre o compósito e seus componentes. Na verdade, existem dois tipos de tais dependencies:

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

insira a descrição da imagem aqui

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

A especificação UML declara: “Uma peça pode ser removida de uma instância composta antes que a instância composta seja excluída e, portanto, não seja excluída como parte da instância composta.” No exemplo de uma composição CarEngine , como mostrado no diagrama a seguir, é claramente o caso que o motor pode ser retirado do carro antes que o carro seja destruído, em cujo caso 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 associação de uma composição no lado composto é 1 ou 0..1, dependendo do fato de os componentes terem um composto obrigatório (deve ser anexado a um composto) ou não. Se os componentes são inseparáveis , isso implica 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 uma relação parte-todo, em que as partes de um todo podem ser compartilhadas com outros conjuntos. Por exemplo, podemos modelar uma agregação entre as classs DegreeProgram e Course , como mostrado no diagrama a seguir, pois 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 poderia compartilhar curso de programação em C com graduação em informática).

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 preferem não usar o diamante branco em seus diagramas de classs, mas apenas modelar uma associação simples em vez de. A especificação da UML diz: “A semântica precisa da agregação compartilhada varia de acordo com a área de aplicação e o modelador”.

A multiplicidade de uma associação de agregação termina em todo o lado pode ser qualquer número (*) porque uma parte pode pertencer ou ser compartilhada entre qualquer número de todos.

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

então esse código …

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

sugere que LineItem é um componente de Order – LineItems não tem existência fora de sua ordem de contenção. Mas os objects Item não são construídos na ordem – eles são passados ​​conforme necessário e continuam a existir, mesmo que a loja não tenha pedidos. então eles estão associados, ao invés de componentes.

* nb o container é responsável por instanciar o componente, mas na verdade ele pode não chamar new … () – sendo este java, geralmente há uma ou duas fábricas para passar primeiro!

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

Eu obtive alguma milhagem fora da UML para geração de código, para código-fonte ou DDL para database relacional. Lá, usei a composição para indicar que uma tabela tem uma chave estrangeira não anulável (no database) e um object “pai” não anulável (e geralmente “final”), no meu código. Eu uso agregação onde pretendo que um registro ou object possa existir como um “órfão”, não anexado a nenhum object pai ou ser “adotado” por um object pai diferente.

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

O exemplo que eu gosto: Composição: A água é uma parte de uma lagoa. (Lagoa é uma composição de água.) Agregação: Lagoa tem patos e peixes (Patos e peixes)

Como você pode ver, usei “parte” e “tem” em negrito, pois essas duas frases normalmente indicam que tipo de conexão existe entre as classs.

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

É 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, sala é uma parte da casa, e a vida na sala começou com a casa da vida e vai terminar quando a vida da casa terminar, sala é uma parte da casa, falamos de composição, como país e capital, livro e páginas. Para exemplo de relação agregada, levar time e jogadores, jogador pode existir sem time, e time é 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 vamos criar equipe, mas para composição não, criamos salas dentro de casa. Composição —-> compósito | compor. Agregação ——-> grupo | elemento

Vamos definir os termos. A Agregação é um metaterm no padrão UML e significa AMBOS composição e agregação compartilhada, simplesmente denominada compartilhada . Para muitas vezes é nomeado incorretamente “agregação”. É RUIM, pois a composição também é uma agregação. Pelo que entendi, você quer dizer “compartilhado”.

Além do padrão UML:

composite – Indica que a propriedade é agregada de forma composta, isto é, o object composto é responsável pela existência e armazenamento dos objects compostos (partes).

Então, universidade para associação de cathedras é uma composição, porque cathedra não existe fora da Universidade (IMHO)

A semântica precisa da agregação compartilhada varia de acordo com a área de aplicação e o modelador.

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

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 do fígado, essas duas partes do corpo estavam em composição com o corpo humano e não podem existir isolamento com o corpo humano.

Mas após o advento do transplante de parte do corpo, eles podem ser transplantados em outro corpo humano, então essas partes estão em agregação com o corpo humano, já que sua existência em isolamento com o corpo humano é possível agora.