Factory Method

Introdução aos Padrões de Criação: Construindo Labirintos

maze1.gif (6360 bytes)

maze2.gif (7510 bytes)

public interface ElementoDeLabirinto {
  public void entra();
}
public class Sala implements ElementoDeLabirinto {
  private ElementoDeLabirinto[] vizinhos =
          new ElementoDeLabirinto[4];
  private int númeroDaSala;

  public Sala(int númeroDaSala) {
    ...
  }
  public void entra() {
    ...
  }
  public ElementoDeLabirinto getVizinho(int direção) {
    ...
  }
  public void setVizinho(int direção,
                         ElementoDeLabirinto vizinho) {
    ...
  }
}

public class Parede implements ElementoDeLabirinto {
  public Parede() {
    ...
  }
  public void entra() {
    ...
  }
}

public class Porta implements ElementoDeLabirinto {
  private ElementoDeLabirinto sala1, sala2;
  private boolean estáAberta;

  public Porta(ElementoDeLabirinto sala1,
               ElementoDeLabirinto sala2) {
    ...
  }
  public void entra() {
    ...
  }
  public ElementoDeLabirinto salaDoOutroLado(ElementoDeLabirinto sala) {
      ...
  }
}
public class Labirinto {
  private Collection salas = new Vector();

  public Labirinto() {
    ...
  }
  public void adicionaSala(ElementoDeLabirinto sala) {
    ...
  }
  public ElementoDeLabirinto getSala(int númeroDaSala) {
    ...
  }
}
public class Jogo {
  ...
  public Labirinto montaLabirinto() {
    Labirinto umLabirinto = new Labirinto();
    Sala sala1 = new Sala(1);
    Sala sala2 = new Sala(2);
    Porta aporta = new Porta(sala1,sala2);

    umLabirinto.adicionaSala(sala1);
    umLabirinto.adicionaSala(sala2);

    sala1.setVizinho(NORTE, new Parede());
    sala1.setVizinho(LESTE, aporta);
    sala1.setVizinho(SUL, new Parede());
    sala1.setVizinho(OESTE, new Parede());

    sala2.setVizinho(NORTE, new Parede());
    sala2.setVizinho(LESTE, new Parede());
    sala2.setVizinho(SUL, new Parede());
    sala2.setVizinho(OESTE, aporta);

    return umLabirinto;
  }
  ...
}

factory2.gif (7891 bytes)

O padrão Factory Method

Objetivo

Também conhecido como

Resumo

Quando usar o padrão Factory Method?

Estrutura genérica

factory1.gif (4955 bytes)

Participantes

Colaborações

Consequências do uso do padrão Factory Method

Considerações de implementação

Exemplo de código: criação de labirintos

public class Jogo {
  // Factory Methods com default
  public Labirinto criaLabirinto() {
    return new Labirinto();
  }
  public Sala criaSala(int númeroDaSala) {
    return new Sala(númeroDaSala);
  }
  public Parede criaParede() {
    return new Parede();
  }
  public Porta criaPorta(Sala sala1, Sala sala2) {
    return new Porta(sala1, sala2);
  }

  // Observe que essa função não tem new:
  // ela usa Factory Methods
  // Esta é a *única* diferença com relação
  // à versão original
  // Observe como o método só trata da estrutura do labirinto
  // e não do tipo de elemento que o compõe
  public Labirinto montaLabirinto() {
    Labirinto umLabirinto = criaLabirinto();
    Sala sala1 = criaSala(1);
    Sala sala2 = criaSala(2);
    Porta aPorta = criaPorta(sala1, sala2);

    umLabirinto.adicionaSala(sala1);
    umLabirinto.adicionaSala(sala2);

    sala1.setVizinho(NORTE, criaParede());
    sala1.setVizinho(LESTE, aporta);
    sala1.setVizinho(SUL, criaParede());
    sala1.setVizinho(OESTE, criaParede());

    sala2.setVizinho(NORTE, criaParede());
    sala2.setVizinho(LESTE, criaParede());
    sala2.setVizinho(SUL, criaParede());
    sala2.setVizinho(OESTE, aporta);

    return umLabirinto;
  }
}
// um novo CriadorConcreto
public class JogoPerigoso extends Jogo {
  public Parede criaParede() {
    return new ParedeDestrutível();
  }
  public Sala criaSala(int númeroDaSala) {
    return new SalaComBomba(númeroDaSala);
  }
}

maze3.gif (8451 bytes)

// um novo CriadorConcreto
public class JogoEncantado extends Jogo {
  public Sala criaSala(int númeroDaSala) {
    return new salaEncantada(númeroDaSala, jogaEncantamento());
  }
  public Porta criaPorta(Sala sala1, Sala sala2) {
    return new portaPrecisandoDeEncantamento(sala1, sala2);
  }
  protected Encantamento jogaEncantamento() {
    ...
  }
}

factory3.gif (7619 bytes)

Pergunta final para discussão

Ver também

programa