Entenda as diferenças nas motivações:
Suponha que você esteja construindo uma ferramenta na qual tenha objetos e uma implementação concreta das inter-relações dos objetos. Como você prevê variações nos objetos, criou um indireto atribuindo a responsabilidade de criar variantes dos objetos para outro objeto ( chamamos de fábrica abstrata ). Essa abstração encontra um grande benefício, pois você prevê futuras extensões que precisam de variantes desses objetos.
Outra motivação bastante intrigante nessa linha de pensamento é um caso em que todos ou nenhum dos objetos de todo o grupo terá uma variante correspondente. Com base em algumas condições, qualquer uma das variantes será usada e, em cada caso, todos os objetos devem ser da mesma variante. Isso pode ser um pouco contra-intuitivo de entender, pois costumamos pensar que - desde que as variantes de um objeto sigam um contrato uniforme comum ( interface em sentido mais amplo ), o código de implementação concreto nunca deve quebrar. O fato intrigante aqui é que, nem sempre isso é verdade, especialmente quando o comportamento esperado não pode ser modelado por um contrato de programação.
Um simples ( emprestando a idéia do GoF ) é qualquer aplicativo GUI, como um monitor virtual que simula a aparência de MS ou Mac ou Fedora OS. Aqui, por exemplo, quando todos os objetos de widget, como janela, botão, etc. possuem variante MS, exceto uma barra de rolagem derivada da variante MAC, o objetivo da ferramenta falha muito.
Esses casos acima formam a necessidade fundamental do Abstract Factory Pattern .
Por outro lado, imagine que você esteja escrevendo uma estrutura para que muitas pessoas possam criar várias ferramentas ( como a dos exemplos acima ) usando sua estrutura. Pela própria idéia de uma estrutura, você não precisa, embora não possa usar objetos concretos em sua lógica. Você prefere colocar alguns contratos de alto nível entre vários objetos e como eles interagem. Enquanto você ( como desenvolvedor de estrutura ) permanece em um nível muito abstrato, cada construtor da ferramenta é forçado a seguir suas construções de estrutura. No entanto, eles ( os construtores de ferramentas ) têm a liberdade de decidir qual objeto será construído e como todos os objetos que eles criarão interagirão. Diferentemente do caso anterior ( do Abstract Factory Pattern ), você ( como criador da estrutura) não precisa trabalhar com objetos concretos nesse caso; e, em vez disso, pode permanecer no nível de contrato dos objetos. Além disso, diferentemente da segunda parte das motivações anteriores, você ou os fabricantes de ferramentas nunca têm a situação de misturar objetos de variantes. Aqui, enquanto o código da estrutura permanece no nível do contrato, todo construtor de ferramentas fica restrito ( pela natureza do caso ) a usar seus próprios objetos. Neste caso, as criações de objetos são delegadas a cada implementador e provedores de estrutura apenas fornecem métodos uniformes para criar e retornar objetos. Tais métodos são inevitáveis para o desenvolvedor da estrutura prosseguir com seu código e tem um nome especial chamado método Factory ( Factory Method Pattern para o padrão subjacente ).
Algumas notas:
- Se você estiver familiarizado com o 'método de modelo', verá que os métodos de fábrica são frequentemente invocados a partir de métodos de modelo no caso de programas pertencentes a qualquer forma de estrutura. Por outro lado, os métodos de gabarito dos programas aplicativos geralmente são implementações simples de algoritmos específicos e nulos de métodos de fábrica.
- Além disso, para a plenitude dos pensamentos, usando a estrutura ( mencionada acima ), quando um construtor de ferramentas está construindo uma ferramenta, dentro de cada método de fábrica, em vez de criar um objeto concreto, ele / ela pode delegar ainda mais a responsabilidade em um resumo objeto de fabricação, desde que o fabricante da ferramenta preveja variações dos objetos de concreto para futuras extensões.
Código de amostra:
//Part of framework-code
BoardGame {
Board createBoard() //factory method. Default implementation can be provided as well
Piece createPiece() //factory method
startGame(){ //template method
Board borad = createBoard()
Piece piece = createPiece()
initState(board, piece)
}
}
//Part of Tool-builder code
Ludo inherits BoardGame {
Board createBoard(){ //overriding of factory method
//Option A: return new LudoBoard() //Lodu knows object creation
//Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
}
….
}
//Part of Tool-builder code
Chess inherits BoardGame {
Board createBoard(){ //overriding of factory method
//return a Chess board
}
….
}