O Padrão Abstract Factory e o Mundo de World of Warcraft

Horda e Aliança

Quando escrevi meu primeiro artigo, “O Padrão State e o Druida de World of Warcraft”, tive a ideia de criar vários artigos explicando os padrões de projeto utilizando exemplos do jogo WoW. Então, espere mais artigos. Desta vez, vamos explorar o padrão criacional Abstract Factory.

O que é o Abstract Factory?

A principal função deste padrão é fornecer uma interface para criar famílias de objetos relacionados ou dependentes, sem especificar suas classes concretas. Ele busca desacoplar o código cliente das classes que realmente produzem os objetos, permitindo maior flexibilidade e escalabilidade. Complexo, né? Vamos para um exemplo simples para maior entendimento.

Exemplo Simples: Uma Fábrica de Comida

Imagine uma fábrica que pode preparar dois tipos de culinária: japonesa e italiana. Cada culinária oferece diferentes pratos, mas todos pertencem a um grupo específico.

Com o padrão Abstract Factory, você simplesmente escolhe o tipo de comida (japonesa ou italiana), e a fábrica cuida de todo o processo, entregando os pratos dessa família sem que você precise conhecer os detalhes internos da preparação.

Um Exemplo Complexo: Horda e Aliança no WoW

No jogo World of Warcraft, existem duas facções rivais: Horda e Aliança (FOR THE HORDE!). Cada facção possui diferentes raças, e cada raça pode pertencer a uma classe específica.

Ao utilizar o padrão Abstract Factory, podemos criar uma estrutura onde o jogador primeiro escolhe a facção, depois a raça e por fim a classe do personagem, sem se preocupar com os detalhes técnicos.

Estrutura do Código:

Interfaces

  • Classe: Define um contrato para todas as classes de personagens.
  • Raça: Define um contrato para todas as raças de personagens.
  • FabricaFaccoes: Define métodos para criar objetos de raça e classe.

Implementações

  • Guerreiro e Paladino: Implementam a interface Classe.
  • Orc e Humano: Implementam a interface Raça.

Fábricas Concretas

  • FabricaHorda: Cria objetos da facção Horda (Orc e Guerreiro).
  • FabricaAlianca: Cria objetos da facção Aliança (Humano e Paladino).

Implementação Detalhada

Interface Classe

package com.cesar.classe;

public interface Classe {
    String mostrarClasse();
}

Implementações:

package com.cesar.classe;

public class Guerreiro implements Classe {
    @Override
    public String mostrarClasse() {
        return "Guerreiro";
    }
}

public class Paladino implements Classe {
    @Override
    public String mostrarClasse() {
        return "Paladino";
    }
}

Interface Raça

package com.cesar.raca;

public interface Raça {
    String mostrarRaça();
}

Implementações:

package com.cesar.raca;

public class Orc implements Raça {
    @Override
    public String mostrarRaça() {
        return "Orc";
    }
}

public class Humano implements Raça {
    @Override
    public String mostrarRaça() {
        return "Humano";
    }
}

Interface FabricaFaccoes

package com.cesar.fabrica;

import com.cesar.classe.Classe;
import com.cesar.raca.Raca;

public interface FabricaFaccoes {
    Raca escolherRaca();
    Classe escolherClasse();
}

Fábricas Concretas

package com.cesar.fabrica;

import com.cesar.classe.Classe;
import com.cesar.classe.Guerreiro;
import com.cesar.raca.Orc;
import com.cesar.raca.Raca;

public class FabricaHorda implements FabricaFaccoes {
    @Override
    public Raca escolherRaca() {
        return new Orc();
    }

    @Override
    public Classe escolherClasse() {
        return new Guerreiro();
    }
}
package com.cesar.fabrica;

import com.cesar.classe.Classe;
import com.cesar.classe.Paladino;
import com.cesar.raca.Humano;
import com.cesar.raca.Raca;

public class FabricaAlianca implements FabricaFaccoes {
    @Override
    public Raca escolherRaca() {
        return new Humano();
    }

    @Override
    public Classe escolherClasse() {
        return new Paladino();
    }
}

Classe Principal

package com.cesar;

import com.cesar.classe.Classe;
import com.cesar.fabrica.FabricaAlianca;
import com.cesar.fabrica.FabricaHorda;
import com.cesar.raca.Raca;
import com.cesar.fabrica.FabricaFaccoes;

public class Main {
    public static void main(String[] args) {
        FabricaFaccoes fabricaHorda = new FabricaHorda();
        Raca racaHorda = fabricaHorda.escolherRaca();
        Classe classeHorda = fabricaHorda.escolherClasse();
        System.out.println("Você escolheu a facção Horda da raça " + racaHorda.mostrarRaça() + " da classe " + classeHorda.mostrarClasse() + ".");

        FabricaFaccoes fabricaAlianca = new FabricaAlianca();
        Raca racaAlianca = fabricaAlianca.escolherRaca();
        Classe classeAlianca = fabricaAlianca.escolherClasse();
        System.out.println("Você escolheu a facção Aliança da raça " + racaAlianca.mostrarRaça() + " da classe " + classeAlianca.mostrarClasse() + ".");
    }
}

Saída Esperada

Você escolheu a facção Horda da raça Orc da classe Guerreiro.
Você escolheu a facção Aliança da raça Humano da classe Paladino.

Código disponível em:

GitHub

Conclusão:

O padrão Abstract Factory é utilizado para:

  • Definir uma interface para criação de famílias de objetos relacionados.
  • Desacoplar o código cliente da lógica de criação dos objetos concretos.

Neste exemplo, as fábricas FabricaHorda e FabricaAlianca criam personagens específicos para cada facção sem expor diretamente os tipos concretos de classes (Orc, Humano, Guerreiro, Paladino).


Publicado

em

por

Etiquetas:

Comentários

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *