Composite Pattern

O Composite é um padrão estrutural que compartilha objetos em estruturas de árvore para representar hierarquias parte-todo, permitindo que clientes tratem objetos individuais e composições de objetos uniformemente. Ele é utilizado para aplicações que desejam ignorar a diferença entre composição de objetos e objetos individuais.

Um exemplo de problema solucionado pelo Composite é o seguinte: um congresso inscreve participantes que podem ser um indivíduo ou uma instituição, e cada indivíduo tem um assento no congresso.

Segue abaixo o diagrama de classes e o código fonte que demonstram a implementação do padrão como solução.

Diagrama de Classes utilizando o padrão Composite
Diagrama de Classes utilizando o padrão Composite como solução

Código da fonte da classe abstrata para componente Participante:

public abstract class Participante {

	public String getNome() {
		throw new UnsupportedOperationException();
	}

	public int getAssento() {
		throw new UnsupportedOperationException();
	}

	public void adicionar(Participante participante) {
		throw new UnsupportedOperationException();
	}

	public void remover(Participante participante) {
		throw new UnsupportedOperationException();
	}

	public Participante getFilho(int index) {
		throw new UnsupportedOperationException();
	}
}

Código fonte da classe folha para tipo primitivo Individuo:

public class Individuo extends Participante {

	private String nome;

	private int assento;

	public Individuo(String nome, int assento) {
		this.nome = nome;
		this.assento = assento;
	}

	@Override
	public String getNome() {
		return nome;
	}

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

	@Override
	public int getAssento() {
		return assento;
	}

	public void setAssento(int assento) {
		this.assento = assento;
	}

	@Override
	public String toString() {
		return "Nome: " + this.nome + " - Assento: " + this.assento;
	}
}

Código fonte da classe composite para tipo composto Instituição:

import java.util.ArrayList;
import java.util.List;

public class Instituicao extends Participante {

	private String nome;

	private List membros;

	public Instituicao(String nome) {
		this.nome = nome;
		membros = new ArrayList();
	}

	@Override
	public void adicionar(Participante participante) {
		membros.add(participante);
	}

	@Override
	public void remover(Participante participante) {
		membros.remove(participante);
	}

	@Override
	public Participante getFilho(int index) {
		return membros.get(index);
	}

	@Override
	public String getNome() {
		return nome;
	}

	public List getMembros() {
		return membros;
	}

	@Override
	public String toString() {
		return "Instituição: " + this.nome;
	}

	public void imprimeMembros() {
	   for (Participante membro : membros) {
	      System.out.println(membro + " - Instituição: " + this.nome);
	   }
	}
}

Código fonte da classe Congresso que usa interface Participante para realizar operações:

import java.util.ArrayList;
import java.util.List;

public class Congresso {

	private String nome;

	private int totalAssentos;

	private List participantes;

	public Congresso(String nome, int totalAssentos) {
	    this.nome = nome;
	    this.totalAssentos = totalAssentos;
	    participantes = new ArrayList();
	}

	public String getNome() {
	    return nome;
	}

	public int getTotalAssentos() {
	    return totalAssentos;
	}

	public int getTotalParticipantes() {
	    int totalParticipantes = 0;

	    for (Participante participante : participantes) {
		if (participante instanceof Individuo) {
		  totalParticipantes++;
		} else if (participante instanceof Instituicao) {
		  Instituicao instituicao = (Instituicao) participante;
		  totalParticipantes += instituicao.getMembros().size();
		}
	    }

	    return totalParticipantes;
	}

	public void adicionarParticipante(Participante participante) {

	   if (participante instanceof Individuo) {

		if (totalAssentos > participantes.size()) {
		  participantes.add(participante);
		} else {
		  throw new UnsupportedOperationException("Congresso não possui 				assentos livres!");
		}

         } else if (participante instanceof Instituicao) {

	    Instituicao t = (Instituicao) participante;

           if (totalAssentos > participantes.size() + t.getMembros().size()) {
				participantes.add(participante);
	    } else {
		throw new UnsupportedOperationException("Congresso não possui"                      		 + " quantidade de assentos livres que Instituição necessita!");	   	    }
	  }
	}

	public void imprimeParticipantes() {
	  System.out.println("----- Listagem de Participantes -----");
	  for (Participante participante : participantes) {
	    if (participante instanceof Individuo) {
	     System.out.println(participante + " - Instituição: Sem Filiação");
	    } else if (participante instanceof Instituicao) {
	     Instituicao instituicao = (Instituicao) participante;
	     instituicao.imprimeMembros();
	    }
	  }
	}

	@Override
	public String toString() {
	   return this.nome + " - Assentos: " + this.totalAssentos
		+ " - Participantes: " + getTotalParticipantes();
	}

	public static void main(String[] args) {
	Congresso congresso = new Congresso("Congresso Nacional", 5);
	  Participante bruno = new Individuo("Bruno Garcia", 1);
	  Participante sarney = new Individuo("José Sarney", 2);

	  congresso.adicionarParticipante(bruno);
	  congresso.adicionarParticipante(sarney);

	  Participante eduardo = new Individuo("Eduardo Suplicy", 3);
	  Participante mercadante = new Individuo("Aloisio Mercadante", 4);

	  Participante partidoTrabalhadores = new Instituicao("PT");
	  partidoTrabalhadores.adicionar(eduardo);
	  partidoTrabalhadores.adicionar(mercadante);

	  congresso.adicionarParticipante(partidoTrabalhadores);

	  System.out.println(congresso);
	  congresso.imprimeParticipantes();
	}
}

Diagrama de sequência para adicionar participantes (individuos ou instituições) no congresso. Clique na imagem para ampliar.

Diagrama de Sequência para Adicionar Participantes no Congresso
Diagrama de de Sequência para Adicionar Participantes no Congresso

9 comentários

  1. Bom dia eu estava querendo um exemplo de diagrama de sequencia do padrao composite mais assim como em seu blog todos os locais so tem exemplos de diagramas de classe. Se nao for pedir muito e se vc saber como ficaria vc poderia postar ou mandar para meu e-mail um exemplo de diagrama de sequencia do composite? pode ser ate com esse seu exemplo do congresso. Obrigada

    gabi_cho07@hotmail.com

    Curtir

  2. Bom dia Gabriela,

    O post foi atualizado com o diagrama de sequência para a ação de adicionar participantes ao congresso. Não sei se é examente isso que você queria. Qualquer dúvida sobre a solução, entre em contato.

    Curtir

  3. Bruno, parabéns!
    Ótimo exemplo de Composite.
    Somente uma observação:uma coisa que me incomodou um pouco foi, na classe: Congresso, no método: +adicionarParticipante(Participante participante) deveria tratar o objetos Individuo e Insituicao de acordo com sua abstração Participcante. Ficou um pouco de mau cheiro utilizar instanceof pois, se vc pensar no principio OCP (Open Close Principle) ao implementar um novo tipo de Participante, a classe Congresso também deverá ser alterada, e, essa alteração na classe Congresso não é interessante.
    Abraço

    Curtido por 1 pessoa

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s