A pattern Builder tem por finalidade isolar a construção de um objeto complexo da sua representação, levando em consideração que o mesmo processo de construção possa criar diferentes representações. Sendo assim, o algoritmo para a construção de um objeto deve ser independente das partes que realmente compõem o objeto e também de como eles são montados.
Utilizando esta pattern, o que temos a fazer é criar uma classe, qual especifica uma interface abstrata para a criação das partes de um objeto-produto. Esta classe abstrata deverá ser herdada pelos objetos concretos que implementaram os métodos de construção para aquele objeto. Esta classe concreta nos fornecerá uma forma de recuperarmos o produto, retornando-o de alguma forma para o cliente que o solicitou.
Vejamos abaixo os participantes envolvidos nesta pattern:
- Director: Constrói um determinado objeto, utilizando a interface de Builder (classe abstrata).
- Builder: Define uma interface abstrata para a criação das partes de um objeto-produto.
- ConcreteBuilder: Implementa os métodos de construção da classe abstrata e também mantém a representação do objeto que cria. Fornece ao cliente um método para a recuperação do produto.
- Product: Representa o objeto complexo em construção, incluindo as interfacces para a montagem das partes no resultado final.
O diagrama abaixo ilustrará estes participantes:

|
Figura 1 – Participantes da Pattern Builder. |
Antes de começarmos a analisar o código da pattern, vamos primeiramente entender o cenário: Teremos dois tipos de objetos complexos, um chamado “Apartamento” e outro chamado “Casa”, pois cada um desses objetos tem particularidades em sua criação, ou seja, implementam diferentemente os métodos de sua construção. Abaixo a classe ConstrucaoBuilder que define a interface necessária para os objetos concretos:
|
|
Public MustInherit Class ConstrucaoBuilder |
|
Protected _dados As Hashtable |
|
Public MustOverride Sub ConstroiParedes() |
Public MustOverride Sub ConstroiJanelas() |
Public MustOverride Sub DefineNumero() |
|
End Class |
|
|
Código 1 – Classe Base que contém a Interface para a criação dos objetos. |
Confrontando o código acima com o modelo estrutural da pattern, esta classe é a que chamamos de “Builder”, que define a interface abstrata. Depois disso, o que temos à fazer é criar uma classe (“Director”) que terá receberá como parâmetro em um método construtor um objeto do tipo da classe abstrata, e internamente será invocado seus métodos para a construção do objeto. O código abaixo ilustra a classe “Director”:
|
|
Public Class Construtora |
|
Public Sub Construir(ByVal construcao As ConstrucaoBuilder) |
construcao.ConstroiJanelas() |
construcao.ConstroiParedes() |
construcao.DefineNumero() |
End Sub |
|
End Class |
|
|
Código 2 – Classe “Director”. |
Como podemos ver, recebemos no parâmetro do método “Construir” um objeto do tipo “ConstrucaoBuilder”, que é o nosso objeto “Builder”. Podemos ver que internamente são invocados os métodos de criação do objeto, definindo assim uma ordem de criação do objeto que está sendo informado e reutilizando o algoritmo (os passos) de criação para todos os objetos.
Feito isso, nos resta implementarmos os nossos objetos complexos (Casa e Apartamento), que obrigatóriamente devem derivar da classe “ConstrucaoBuilder”, implementando os seus métodos de criação e retorno para o cliente. Abaixo o código relacionado ao nosso objeto “Apartamento”:
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
|
|
Public Class Apartamento |
|
Inherits ConstrucaoBuilder |
|
Public Overrides Sub ConstroiJanelas |
_dados = New Hashtable |
_dados.Add(“Janelas”, “2”) |
End Sub |
|
Public Overrides Sub ConstroiParedes |
_dados.Add(“Paredes”, “12”) |
End Sub |
|
Public Overrides Sub DefineNumero |
_dados.Add(“Número”, “A-56”) |
End Sub |
|
Public Sub VisualizarConstrucao |
Console.WriteLine(“APARTAMENTO:”) |
For Each d As DictionaryEntry In _dados |
Console.WriteLine(“{0}: {1}”, d.Key, d.Value) |
Next |
Console.WriteLine() |
End Sub |
|
End Class |
|
|
Código 3 – Classe Apartamento (“ConcreteBuilder”). |
Vemos que ao herdar a classe “ConstrucaoBuilder” os métodos “ConstroiJanelas”, “ConstroiParedes”, “DefineNumero” e criamos um método chamado “VisualizarConstrucao” para devolver ao cliente o resultado gerado. Por questões de exemplo, a classe “Casa” tem a mesma estrutura interna em seus métodos de construção e sendo assim, vamos ocultá-la aqui por questões de espaço, mas pode consultá-la no código fonte do artigo.
E finalmente, a chamada no cliente fica:
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
|
|
Sub Main() |
|
Dim construtora As New Construtora |
Dim apto As New Apartamento |
Dim casa As New Casa |
|
construtora.Construir(apto) |
construtora.Construir(casa) |
|
apto.VisualizarConstrucao() |
casa.VisualizarConstrucao() |
|
End Sub |
|
|
Código 4 – Consumindo as classes no cliente. |
Vemos que criamos/configuramos a instância de uma classe do tipo “Construtora” que é o nosso “Director”, que envia as solicitações ao Builder, que este por sua vez fará o seu trabalho de construção de uma determinada parte do objeto concreto. Criamos também mais dois objetos, sendo um do tipo “Apartamento” e outro do tipo “Casa”, quais são posteriormente passados para o método “Construir” do nosso Director, e este executa os métodos de construção respectivos do objeto em questão.
Pode-se reparar, que independentemente do objeto passado para o método construtor de nosso “Director”, o processo de criação do objeto será executado – baseando-se na instância do mesmo – e assim percebemos que separamos a criação dos objetos complexos da sua representação mas utilizando o mesmo processo, ou melhor, os mesmo passos, possibilitando diferentes representações.
Aplica-se esta pattern quando o algoritmo de criação de um objeto complexo deve ser independente das partes que o compõem das quais são montadas e também quando deverá permitir diferentes representações para o objeto que é construído.
CONCLUSÃO: Apesar de ser uma pattern de utilização 3 em uma escala de 0 à 5, é útil quando necessitamos separar a construção de um objeto complexo da sua representação, criando assim, diversas representações deste objeto.
OOBuilder.zip (17.17 kb)
Curtir isso:
Curtir Carregando...