Padrões de projeto em .NET: Abstract Factory

Também conhecido como Kit, este padrão fornece uma interface para criação de famílias de objetos relacionados ou dependentes sem especificar suas classes concretas...

Padrões de projeto em .NET: Abstract Factory

 

Também conhecido como Kit, este padrão fornece uma interface para criação de famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.

 

Para esclarecer a motivação para utilização deste padrão, considere a construção de um carro. Ao escolher um carro de uma determinada marca e modelo, um comprador sabe que está levando para casa, obrigatoriamente, determinadas peças. Porém, ele sabe, também, que itens como cor, airbag e direção hidráulica são itens opcionais, ou seja, podem estar presentes no carro a ser comprado ou não, influenciando em seu preço. Para ser portátil entre as várias opções, uma aplicação não deve codificar rigidamente seus componentes para um determinado padrão. Instanciando classes específicas de personalização pela aplicação toda torna difícil mudar tal personalização no futuro.

 

Podemos resolver esse problema definindo uma classe abstrata CarroFactory que declara uma interface para criação de cada tipo básico de carro. Existe, também, uma classe abstrata para cada tipo de carro, e subclasses concretas implementam os componentes para personalização. A interface de CarroFactory tem uma operação que retorna um novo objeto Carro para cada classe abstrata de Carro. Os clientes chamam estas operações para obter instâncias de Carro, mas não têm conhecimento das classes concretas que estão usando. Desta forma, os clientes ficam independentes do padrão de personalização usado no momento.

 

Existe uma subclasse concreta de CarroFactory para cada tipo de personalização. Cada subclasse implementa as operações para criar o carro apropriado para aquele tipo de personalização. Por exemplo, a operação CriarMotor aplicada à PoloCarroFactory instancia e adiciona um componente motor ao carro, de acordo com os padrões Volkswagen para o modelo Polo, enquanto que a mesma operação aplicada à StiloCarroFactory instancia um componente motor ao carro de acordo com os padrões Fiat para o modelo Stilo. Os clientes criam componentes exclusivamente através da interface de CarroFactory e não têm conhecimento das classes que implementam os componentes para um padrão específico. Em outras palavras, os clientes têm somente que se comprometer com uma interface definida por uma classe abstrata, não uma determinada classe concreta. Uma CarroFactory também implementa e garante as dependências entre as classes concretas de componentes. Um motor para o modelo Volkswagen Polo deveria ser usado somente com um carro modelo Volkswagen Polo, e essa restrição é garantida automaticamente como conseqüência de usar uma PoloCarroFactory

 

Quando usar Abstract Factory?

Use o padrão Abstract Factory quando:

 

 

Estrutura

 

 

Vantagens e desvantagens

O padrão Abstract Factory tem as seguintes vantagens e desvantagens:

 

Exemplo de código

Aplicaremos o padrão AbstractFactory para criar os carros que discutimos no início do artigo.

 

A classe CarFactory pode criar modelos de carros e seus respectivos componentes. Ela define motor, pneu, porta, entre outros. Esta classe pode ser usada por uma aplicação que lê as especificações de um determinado modelo de carro em um arquivo XML, por exemplo, e constrói o respectivo carro, ou pode ser usada por uma aplicação que constrói carros aleatoriamente. As aplicações que constroem os carros recebem CarFactory como parâmetro, de maneira que o desenvolvedor possa especificar as classes de motor, pneu e porta a serem construídas.

 

Public Interface ICarroFactory

 

Function CriarCarro() As ICarro

Function CriarMotor() As IMotor

Function CriarPneu() As IPneu

Function CriarPorta() As IPorta

 

End Interface

 

Vale frisar que a função MontarCarro cria um carro básico, consistindo em 2 portas, 4 pneus e 1 motor. É claro que estes itens não são suficientes para que um carro funcione. Porém, a intenção, aqui, é exemplificar a utilização do padrão AbstractFactory.

 

Public Function MontarCarro(ByVal factory As ICarroFactory) As ICarro

 

Dim ListaPneus As List(Of IPneu)

Dim ListaPortas As List(Of IPorta)

 

Dim OCarro As ICarro = factory.CriarCarro

Dim OMotor As IMotor = factory.CriarMotor

 

Dim OPneu1 As IPneu = factory.CriarPneu

ListaPneus.Add(OPneu1)

Dim OPneu2 As IPneu = factory.CriarPneu

ListaPneus.Add(OPneu2)

Dim OPneu3 As IPneu = factory.CriarPneu

ListaPneus.Add(OPneu3)

Dim OPneu4 As IPneu = factory.CriarPneu

ListaPneus.Add(OPneu4)

 

Dim OPorta1 As IPorta = factory.CriarPorta

ListaPortas.Add(OPorta1)

Dim OPorta2 As IPorta = factory.CriarPorta

ListaPortas.Add(OPorta2)

 

OCarro = AdicionarMotor(OMotor)

 

For Each OPneu As IPneu In ListaPneus

OCarro = AdicionarPneu(OPneu)

Next

 

For Each OPorta As IPneu In ListaPortas

OCarro = AdicionarPorta(OPorta)

Next

 

Return OCarro

 

End Function

 

Podemos criar PoloCarroFactory, uma fábrica para carros do modelo Volkswagen Polo.

 

Public Class PoloCarroFactory

 Implements ICarroFactory

 

Public Function CriarCarro() As ICarro Implements ICarroFactory.CriarCarro

Return New CarroPolo

End Function

 

Public Function CriarMotor() As IMotor Implements ICarroFactory.CriarMotor

Return New MotorPolo

End Function

 

Public Function CriarPneu() As IPneu Implements ICarroFactory.CriarPneu

Return New PneuPolo

End Function

 

Public Function CriarPorta() As IPorta Implements ICarroFactory.CriarPorta

Return New PortaPolo

End Function

End Class

 

E podemos, também, criar StiloCarroFactory, para carros do modelo Fiat Stilo.

 

Public Class StiloCarroFactory

Implements ICarroFactory

 

Public Function CriarCarro() As ICarro Implements ICarroFactory.CriarCarro

Return New CarroStilo

End Function

 

Public Function CriarMotor() As IMotor Implements ICarroFactory.CriarMotor

Return New MotorStilo

End Function

 

Public Function CriarPneu() As IPneu Implements ICarroFactory.CriarPneu

Return New PneuStilo

  End Function

 

Public Function CriarPorta() As IPorta Implements ICarroFactory.CriarPorta

Return New PortaStilo

End Function

End Class

 

Repare que, para ambos os modelos, as classes são implementadas pela mesma interface, assim como seus métodos retornam objetos das mesmas interfaces. Isso garante que todos os carros, independente do modelo, terão 1 motor, 4 pneus e 2 portas. Porém, quesitos específicos de cada modelo, como design da porta, marca dos pneus e especificações de motor são informados de forma independente por cada fabricante, Fiat ou Volkswagen, de acordo com as implementações que seus desenvolvedores farão sobre cada interface.

 

No próximo artigo estaremos discutindo mais um padrão de criação: o Builder.
Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados