Composição Vs. Agregação

Boa noite! Pessoal

Gostaria que vocês analisassem se os meus conceitos a respeito de composição e agregação estão corretos, pois acabo sempre me confundindo quando me esbarro neste assunto. Segue abaixo o conceito pelo qual eu entendi e os exemplos de código que eu mesmo desenvolvi.

Conceito de composição:
Composição é um tipo de associação mais forte que a agregação, pois a composição é um relacionamento caracterizado como PARTE-TODO, mas em caso de composição o TODO ele é responsável pelo ciclo de vida da PARTE, sendo assim a composição é aplicada quando a PARTE não faz sentido existir sem o TODO e quando o objeto que representa o TODO for destruido a PARTE também deverá ser destruída.

Exemplo de implementação de composição: Neste exemplo a classe Automovel estará representando o TODO e a classe Motor representando a PARTE.

package exemplo;

public class Motor {

	/*
	 * Atributos.
	 */
	private int potencia;

	/*
	 * Método construtor passando a potência do objeto motor como parâmetro
	 */
	public Motor(int potencia) {
		this();
		this.potencia = potencia;
	}

	/*
	 * Método construtor padrão
	 */
	public Motor() {
		super();
	}

	/*
	 * Métodos Getters and Setters
	 */
	public int getPotencia() {
		return this.potencia;
	}

	public void setPotencia(int potencia) {
		this.potencia = potencia;
	}

	/*
	 * Método toString() para impressão em formato String do objeto Motor
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Motor [potencia=");
		builder.append(potencia);
		builder.append("]");
		return builder.toString();
	}

}
package exemplo;

public class Automovel {

	/*
	 * Atributos.
	 */
	private String modelo;

	/*
	 * Atributo motor faz referência a um objeto do tipo Motor.
	 */
	private Motor motor;

	/*
	 * Método construtor passando como parâmetro uma String que indicará o
	 * modelo do Automovel e um int que indicará a potência do Motor que será
	 * instânciado dentro do deste método construtor.
	 */
	public Automovel(String modelo, int potenciaMotor) {
		this();
		this.modelo = modelo;
		/*
		 * Um objeto do tipo Motor sendo instânciado dentro do método construtor
		 * da classe Automovel sendo assim será gerada uma associção do tipo
		 * composição, pois o objeto Motor existirá somente enquanto o objeto
		 * Automovel existir.
		 */
		this.motor = new Motor(potenciaMotor);
	}

	/*
	 * Método construtor padrão.
	 */
	public Automovel() {
		super();
	}

	/*
	 * Métodos Getters and Setters.
	 */
	public String getModelo() {
		return this.modelo;
	}

	public void setModelo(String modelo) {
		this.modelo = modelo;
	}

	public Motor getMotor() {
		return this.motor;
	}

	public void setMotor(Motor motor) {
		this.motor = motor;
	}

	/*
	 * Método toString() para impressão em formato String do objeto Automovel.
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Automovel [modelo=");
		builder.append(modelo);
		builder.append(", motor=");
		builder.append(motor);
		builder.append("]");
		return builder.toString();
	}

}
package exemplo;

public class TesteComposicao {

	public static void main(String[] args) {
		Automovel gol = new Automovel("Gol 1.0", 1000);
		System.out.println(gol.toString());
	}
}

Conceito de agregação:
Agregação é um tipo de relacionamento caracterizado como PARTE-TODO, mas diferente da composição, pois agregação ocorre quando um determinado objeto que representa a PARTE do TODO faça sentido que sobreviva sem o TODO, mesmo que o TODO não exista.

Exemplo de implementação de agregação: Neste exemplo reutilizei as classes do exemplo anterior, somente adicionando a classe Motorista e fazendo algumas modificações na classe Automovel.

package exemplo;

public class Motor {

	/*
	 * Atributos.
	 */
	private int potencia;

	/*
	 * Método construtor passando a potência do objeto motor como parâmetro
	 */
	public Motor(int potencia) {
		this();
		this.potencia = potencia;
	}

	/*
	 * Método construtor padrão
	 */
	public Motor() {
		super();
	}

	/*
	 * Métodos Getters and Setters
	 */
	public int getPotencia() {
		return this.potencia;
	}

	public void setPotencia(int potencia) {
		this.potencia = potencia;
	}

	/*
	 * Método toString() para impressão em formato String do objeto Motor
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Motor [potencia=");
		builder.append(potencia);
		builder.append("]");
		return builder.toString();
	}

}
package exemplo;

public class Motorista {

	/*
	 * Atributos.
	 */
	private String nome;
	private int habilitacao;
	
	/*
	 * Método construtor passando como parâmetro uma String representando 
	 * o nome do objeto Motorista e um int representando a habilitação.
	 */
	public Motorista(String nome, int habilitacao) {
		this();
		this.nome = nome;
		this.habilitacao = habilitacao;
	}

	/*
	 * Método construtor padrão.
	 */
	public Motorista() {
		super();
	}

	/*
	 * Métodos Getters and Setters.
	 */
	public String getNome() {
		return this.nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public int getHabilitacao() {
		return this.habilitacao;
	}

	public void setHabilitacao(int habilitacao) {
		this.habilitacao = habilitacao;
	}

	/*
	 * Método toString() para impressão em formato String do objeto Motorista.
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Motorista [nome=");
		builder.append(nome);
		builder.append(", habilitacao=");
		builder.append(habilitacao);
		builder.append("]");
		return builder.toString();
	}

}
package exemplo;

public class Automovel {

	/*
	 * Atributos.
	 */
	private String modelo;

	/*
	 * Atributo motor faz referência a um objeto do tipo Motor.
	 */
	private Motor motor;

	/*
	 * Atributo motor faz referência a um objeto do tipo Motorista.
	 */
	private Motorista motorista;

	/*
	 * Método construtor sobrecarregado adicionando o parâmetro do tipo
	 * Motorista neste caso o motorista não será instânciado dentro do
	 * construtor da classe Automovel, será instânciado fora desta e adicionado
	 * a lista de parâmetros deste contrustor, pois caso o objeto Automovel seja
	 * destruído o objeto Motorista continuará existindo.
	 */
	public Automovel(String modelo, int potenciaMotor, Motorista motorista) {
		this(modelo, potenciaMotor);
		this.motorista = motorista;
	}

	/*
	 * Método construtor passando como parâmetro uma String que indicará o
	 * modelo do Automovel e um int que indicará a potência do Motor que será
	 * instânciado dentro do deste método construtor.
	 */
	public Automovel(String modelo, int potenciaMotor) {
		this();
		this.modelo = modelo;
		/*
		 * Um objeto do tipo Motor sendo instânciado dentro do método construtor
		 * da classe Automovel sendo assim será gerada uma associção do tipo
		 * composição, pois o objeto Motor existirá somente enquanto o objeto
		 * Automovel existir.
		 */
		this.motor = new Motor(potenciaMotor);
	}

	/*
	 * Método construtor padrão.
	 */
	public Automovel() {
		super();
	}

	/*
	 * Métodos Getters and Setters.
	 */
	public String getModelo() {
		return this.modelo;
	}

	public void setModelo(String modelo) {
		this.modelo = modelo;
	}

	public Motor getMotor() {
		return this.motor;
	}

	public void setMotor(Motor motor) {
		this.motor = motor;
	}

	public Motorista getMotorista() {
		return motorista;
	}

	public void setMotorista(Motorista motorista) {
		this.motorista = motorista;
	}

	/*
	 * Método toString() para impressão em formato String do objeto Automovel.
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Automovel [modelo=");
		builder.append(modelo);
		builder.append(", motor=");
		builder.append(motor);
		builder.append(", motorista=");
		builder.append(motorista);
		builder.append("]");
		return builder.toString();
	}

}
package exemplo;

public class TesteAgregacao {

	public static void main(String[] args) {
		Motorista motorista = new Motorista("Renato", 1234567);
		Automovel gol = new Automovel("Gol 1.0", 1000, motorista);
		System.out.println(gol.toString());
	}
}
1 curtida

Imagino que você esteja buscando esses conceitos por estar estudando UML…

Vou te dar uma dica (como diria os americanos, coloque um pouco de sal):

[UML][ ABISMO ][PROGRAMAÇÃO]

A uml vai ter uns conceitos que a aplicação direta na programação não será tão viável. Nesse seu exemplo, depende do que o motorista representa para o automóvel. O motorista pode ou não existir sozinho. O mesmo vale apara o motor.

Mas vou dar um outro exemplo que talvez facilite a visão.

Pense em um grupo de empresas. Um grupo de empresas só existe, se existirem filiais. Se acabarem com todas as filiais não haverá mais o grupo.
Isso é composição. Um grupo de empresas é composto de filiais.

Mas no miolo ali da programação, não será bem assim que funciona. Sempre você poderá ter objetos GrupoDeEmpresa, sem ter objetos Filial. Sacou? O relacionamento do conceito projetado no seu diagrama UML não será refletido rigorosamente na sua programação. Servirá apenas como conceito mesmo.

Agregação é mais fácil, os dois exemplos que você deu podem ser enxergados como agregação.

Lembre-se, agregação ou composição não é um estado fixo para as mesmas coisas sempre. Depende da semântica do seu sistema.

1 curtida

Valeu rogelgarcia!

Então pelo que entendi agora, você quis dizer que a agregação e composição só é refletida na UML em minha documentação e não no código?

Isso… o que você faz na UML não reflete fielmente no código.

Reflete no código até certo ponto. Por exemplo, existirá um relacionamento entre as classes. Mas diferenciar composição e agregação no código, é bem complicado. Como eu disse, a diferença é mais conceitual do que pragmática.

O que você falou é verdade, pois pelo o que estou vendo o pessoal comentando que agregação e composição a nível de implementação é mesma coisa, a única coisa difere é o esquema da modelagem UML