Os padrões de projetos ajudam estruturar programas de maneiras mais flexíveis, fáceis de entender e manter. Através deles sistemas são construídos com boas qualidades de design orientado à objetos(OO). Eles nos fornecem soluções gerais para problemas de projeto. Esse artigo explica o padrão abstract factory mostrando seu uso e estrutura aplicada no contexto de uma loja de bolo.
No artigo sobre o Padrão factory method aprendemos uma maneira de encapsular a criação de objetos. Enquanto o padrão factory method utiliza a herança para criar uma instância, o padrão abstract factory utiliza a composição para criar uma família de produtos. Os dois padrões encapsulam a criação de objetos para manter os aplicativos levemente ligados e menos dependentes das implementações, ou seja, os clientes da fábrica são desvinculados dos produtos concretos reais que utilizam.
O diagrama de classes do padrão Abstract Factory é mostrado a seguir:
Um cliente é escrito para uma fábrica abstrata, no tempo de execução ele escolhe uma fábrica concreta a qual instância uma família de produtos (ProdutoA e ProdutoB, em nosso exemplo). A AbstractFactory define a interface que todas as fábricas concretas devem implementar. Dessa forma, a familía de produtos é estabelecida.
Aplicando o padrão Abstract Factory na loja de bolo:
O cliente de AbstractFactory é a instância de nossa CakeStore, DeliciousCake. A CakeIngredientFactory é a interface que define como criar uma família de produtos relacionados para fazer um bolo. A função das fábricas de bolo concretas é produzir os ingredientes dos bolos. Cada fábrica sabe como criar os objetos certos para um determinado tipo de bolo. A ChocolateCakeIngredientFactory cria massa convencional e cobertura de chocolate, enquanto a CoconutCakeIngredientFactory cria massa integral e cobertura de coco.
Código da classe CakeStore:
package com.programacao4devs.abstractfactory.cakestore;
import com.programacao4devs.abstractfactory.product.Cake;
public abstract class CakeStore {
protected abstract Cake createCake(String type);
public Cake orderCake(String type) {
Cake cake;
cake = createCake(type);
cake.prepare();
cake.bake();
cake.cut();
cake.box();
return cake;
}
}
Código da classe DeliciousCakes:
public class DeliciousCakes extends CakeStore {
@Override
protected Cake createCake(String type) {
Cake cake = null;
CakeIngredientFactory ingredientFactory;
if (type.equals("chocolate")) {
ingredientFactory = new ChocolateCakeIngredientFactory();
cake = new ChocolateCake(ingredientFactory);
cake.setName("Chocolate Cake");
} else if (type.equals("coconut")) {
ingredientFactory = new CoconutCakeIngredientFactory();
cake = new CoconutCake(ingredientFactory);
cake.setName("Coconut Cake");
}
return cake;
}
}
Código da classe Cake:
public abstract class Cake {
protected String name;
protected Dough dough;
protected Topping topping;
public abstract void prepare();
public void bake() {
System.out.println("Bake for 40 minutes at 180");
}
public void cut() {
System.out.println("Cutting the cake into square slices");
}
public void box() {
System.out.println("Place cake in official CakeStore box");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Código da classe CoconutCake:
public class CoconutCake extends Cake {
CakeIngredientFactory ingredientFactory;
public CoconutCake(CakeIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
@Override
public void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
topping = ingredientFactory.createTopping();
}
}
Código da classe CoconutCakeIngredientFactory:
public class CoconutCakeIngredientFactory implements CakeIngredientFactory {
@Override
public Dough createDough() {
return new WholeWheatDough();
}
@Override
public Topping createTopping() {
return new CoconutTopping();
}
}
Código da classe ApplicationCakeStore para executar o teste:
public class ApplicationCakeStore {
public static void main(String[] args) {
CakeStore cakeStore = new DeliciousCakes();
Cake cake = cakeStore.orderCake("coconut");
System.out.println("Order placed for a " + cake.getName() );
}
}
Resultado mostrado no Console:
Preparing Coconut Cake
Bake for 40 minutes at 180
Cutting the cake into square slices
Place cake in official CakeStore box
Order placed for a Coconut Cake
Download do código completo em: https://github.com/programacao4devs/padrao-abstract-factory
Os princípios OO utilizados no padrão abstract factory:
Inscreva seu nome e email na Programacao4Devs para receber atualizações de novos artigos, tutoriais e dicas.
Sua inscrição foi registrada. Obrigado!