10/11/2016

Design Patterns - Patterns Criacionais: Abstract Factory

Munir Alviani Mourad

Munir Alviani
Diretor de Projetos

A Abstract Factory é a primeira Design Pattern descrita no popular livro Design Patterns do GoF (gang of Four, os quatro escritores que ficaram famosos pelo catálogo de Design Patterns até hoje mais famoso). Ela faz parte da categoria de Patterns Criacionais, cujo objetivo é a instanciação de objetos. Essa categoria é importante pois ela sustenta o princípio mais importante do livro: "programe para interfaces e não para implementações".

Todas as patterns tratam a respeito de relações entre os objetos, de forma que eles sejam independentes das implementações. Porém, em algum momento esses objetos deverão ser instanciados, e aí entram em cena as Patterns Criacionais, cujo único objetivo é a instanciação de objetos de forma que seu sistema continue independente de implementações.

Posso dizer que, atualmente, essas patterns criacionais estão em desuso, sendo substituídas pelos frameworks de Injeção de Dependência, que fazem exatamente isso: instanciam para você as classes das quais você é dependente. De toda forma, conhecer as patterns, a sua motivação e entender as suas consequências é um bom exercício de design de software.

O problema específico que a AbstractFactory tenta resolver é da instanciação na existência de uma família de produtos. O exemplo dado no livro é o seguinte: você tem elementos visuais (produtos), como Window, ScrollBar, Menu e etc. Esses elementos visuais têm diferentes implementações para cada família de implementação gráfica, como o Microsoft Windows, o MAC, e X do Linux.

Nesse caso, a solução consiste de duas coisas:

1. Crie interfaces padrões para os diferentes produtos dessa família (como Window, ScrollBar e Menu). E todo o seu sistema vai trabalhar apenas com essas interfaces que você definiu.

2. Defina uma AbstractFactory, que tem os métodos de instanciação para cada uma dessas interfaces padrões definidas acima, no caso, os métodos para o exemplo seriam: CreateWindow, CreateScrollBar, CreateMenu. Toda hora que o seu sistema precisa de instâncias dos produtos ele as obterá através dessa AbstractFactory.  Algo como factory.CreateWindow()

Mas de onde virá essa factory? Em algum lugar, provavelmente na inicialização do seu sistema, você define qual AbstractFactory você vai fornecer ao seu sistema, e repassa essa factory a todos os objetos que precisarem dela. Veja o esquema:

Esquema AbstractFactory

Na figura acima, retirada do livro, o Client, que representa o “resto do seu sistema”, utiliza as classes abstratas dos produtos (AbstractProductA e AbstractProductB) e a AbstractFactory, assim como foi explicado.

É importante agora analisar os benefícios e malefícios dessa pattern. O ponto principal é que a pattern deixa seu sistema independente das diferentes famílias, ou seja, garante o baixo acoplamento citado anteriormente.

Outro ponto positivo é que a pattern permite adicionar, remover ou modificar rapidamente qual família de produtos deseja-se usar. Isso pode até ser feito em runtime, se usado com um pouco de Reflection para instanciar uma fábrica através de um parâmetro (ou com um array associativo das possíveis fábricas).

O ponto negativo desse pattern é que a adição ou remoção de um produto da família exige a modificação da AbstractFactory, o que causa um grande overhead, pois deve-se modificar todas as implementações da factory e o cliente que usa a AbstractFactory.

Na verdade, usando-se Reflection pode-se até criar um único método “Create” que recebe como parâmetro alguma indicação de qual produto ele deve criar (uma string com o nome da classe, por exemplo). Assim, você poderia criar um novo produto sem muitos problemas, basta passar o parâmetro certo. Mas isso funciona como uma balança: se você ganha flexibilidade na criação de novos produtos, você perde com a necessidade de uma interface única para todos esses produtos, já que eles serão retornados pelo mesmo método “Create”.  E o seu client precisará fazer um cast para o produto específico.

Adicione um novo comentário