Padrões de Projeto – Builder

3 06 2009

Só pra dar uma movimentada no blog, vou postar o source de um trabalho de Engenharia de Software sobre Design Patterns, meu grupo ficou incumbido de descrever e exemplificar os padrões Builder, State e Flyweight.

Pra quem não sabe, Padrões de Projeto (aka Design Patterns) são soluções genéricas pra problemas diversos :) múito esclarecedor não acham??? Em projetos de software orientados a objetos vez por outra nos deparamos com pequenos problemas como: “poxa, o essa classe legada tem  tais métodos, preciso usar ela mas meu projeto mas esses métodos deveria ter outros parametros… to ferrado”, e para algumas destes problemas foram catalogadas soluções que, não apenas resolvem o problema, mas o faz de forma a não “estragar” seu projeto.

Essas soluções não estão prontas para serem usadas  elas são apenas um esboço que cada um utiliza de acordo com suas necessidades,  combinando com outros Padrões de Projeto conforme sua necessidade. Um outro ponto a destacar em Design Patterns é que  eles trazem a idéia de “Programar par a Interfaces (de classe, não visuais)” o que dá maior flexibilidade e consequentemente tornando menos difícil de alterar quando necessário.

Os exemplos que eu vou mostrar são em C# porém podem ser implementados também em qualquer linguagem com suporte a orienteção a objetos (Java, C++, SmallTalk, Delphi (ou object pascal como preferir), Visual Basic,…)

Padrão Builder

Objetivo: “Separar o construtor de um objeto complexo de sua representação, para que o mesmo processo de construção nos permita criar diferentes representações”.

Classe de Veículo

Classe de Veículo

Explicando: Suponhamos que você tenha um objeto Veículo em seu sistema, esse veículo representar um carro, uma moto, um avião, uma bicicleta entre outros ou seja, cada ítem listado é uma representação de um veículo.

Para representar uma bicicleta usando a classe veículo você teria que fazer algo como:

  Veiculo = new Veiculo();
  Veiculo.Chassi = "Chassi de bicicleta";
  Veiculo.Rodas = 2;
  Veiculo.Motor = "Pernas";

Agora imagine fazer isso para cada representação que você tiver em seu sistema, lembre-se estamos falando de objetos complexos que  geralmente serão mais complexos do que este exemplo.

A solução é separar o construtor da representação fazendo com que a responsabilidade de definir as propriedades de cada uma delas não sejam da classe veículo ou da classe chamadora mas sim de uma classe especialmente criada para isso, teremos então a seguinte estrutura:

Exemplo do padrão Builder

Exemplo do padrão Builder

Qual a vantagem?

using System;

namespace Builder
{
	class Program
	{
		public static void Main(string[] args)
		{
			Construtor construtor = new Construtor();

			CarBuilder FabricadeCarro = new CarBuilder();
			MotoBuilder FabricadeMoto = new MotoBuilder();
			TricicloBuilder FabricaDeTriciclo = new TricicloBuilder();

			construtor.Construir(FabricadeCarro);
			FabricadeCarro.produto.Mostrar();

			construtor.Construir(FabricadeMoto);
			FabricadeMoto.produto.Mostrar();

			construtor.Construir(FabricaDeTriciclo);
			FabricaDeTriciclo.produto.Mostrar();

			Console.ReadKey(true);
		}
	}
}

Código mais claro, liberdade para incluir várias representações apenas criando suas classes construtoras.

Segue código fonte completo:

using System;

namespace Builder
{
	public class Construtor{
		public void Construir(Builder build){
			build.Chassi();
			build.Motor();
			build.NumPneus();
		}
	}

	public interface Builder{
		void Chassi();
		void NumPneus();
		void Motor();
	}

	public class CarBuilder:Builder{
		public Produto produto;
		public CarBuilder(){
			produto = new Produto("Carro");
		}

		public void Chassi(){
			produto.Chassi = "Chassi de Carro";
		}

		public void NumPneus(){
			produto.NumPneus = "4";
		}		

		public void Motor(){
			produto.Motor = "400cc";
		}
	}

	public class MotoBuilder:Builder{
		public Produto produto;
		public MotoBuilder(){
			produto = new Produto("Moto");
		}

		public void Chassi(){
			produto.Chassi = "Chassi de Moto";
		}

		public void NumPneus(){
			produto.NumPneus = "2";
		}

		public void Motor(){
			produto.Motor = "1200cc";
		}
	}

	public class TricicloBuilder:Builder{
		public Produto produto;
		public TricicloBuilder(){
			produto = new Produto("Triciclo");
		}

		public void Chassi(){
			produto.Chassi = "Chassi de Triciclo";
		}

		public void NumPneus(){
			produto.NumPneus = "3";
		}

		public void Motor(){
			produto.Motor = "40cc";
		}
	}

	public class Produto{
		public string Nome;
		public string Chassi;
		public string NumPneus;
		public string Motor;

		public Produto(string aNome){
			Nome = aNome;
		}

		public void Mostrar(){
			Console.WriteLine("-----------------");
			Console.WriteLine("Nome: "+Nome);
			Console.WriteLine("Chassi: "+Chassi);
			Console.WriteLine("Num Pneus: "+NumPneus);
			Console.WriteLine("Motor: "+Motor);
		}

	}
}

Referências:

  • Design patterns : elements of reusable object-oriented software. Addison Wesley, 1995

Ações

Informações

Deixe um comentário