# Padrões de desenho

Os dez padrões do programa aplicados a problemas concretos do jogo.

Página: https://resumos.rgo.pt/cadeiras/ldts/padroes-desenho/

Um **padrão de desenho** é uma solução reutilizável para um problema recorrente, com nome, estrutura e consequências conhecidas. O programa lista dez: Factory-Method, Command, Composite, Observer, Strategy, Abstract Factory, State, Adapter, Decorator e Singleton. Não os decores como definições: aprende a reconhecer o problema que cada um resolve, porque nos exercícios e nas provas a pergunta é sempre “que padrão aplicavas aqui”.

## Os dez padrões em rascunho rápido

**Strategy** troca algoritmos em tempo de execução: o `Monstro` recebe um `Comportamento` diferente. Usa quando há várias formas de fazer a mesma coisa.

**State** troca comportamento conforme o estado interno: um monstro calmo foge, um monstro alerta persegue. Usa quando um objeto se comporta de forma muito diferente consoante o estado, em vez de um `switch` gigante.

**Observer** avisa interessados quando algo muda: a pontuação observa os monstros e atualiza-se quando um cai. Usa para dependências um para muitos sem acoplamento.

**Command** transforma um pedido num objeto: cada tecla vira um `Comando` com `executar`. Usa para desfazer, filas e menus.

**Factory Method** e **Abstract Factory** criam objetos sem expor a classe concreta. A diferença está no tamanho da encomenda: o Factory Method cria **um** objeto (uma fábrica de monstros que devolve o tipo certo para cada nível), enquanto a Abstract Factory cria **famílias** coerentes (uma fábrica de nível que devolve monstros, paredes e itens no mesmo estilo). Usa o primeiro quando a criação de um objeto tem lógica, o segundo quando vários objetos têm de combinar entre si.

**Composite** trata um grupo como um objeto: uma parede feita de segmentos desenha-se como uma peça. Usa para estruturas em árvore.

**Decorator** acrescenta comportamento por embrulho: um monstro com bónus de velocidade embrulha o monstro base. Usa para combinações que explodiriam em subclasses.

**Adapter** converte uma interface noutra: adapta a biblioteca de ecrã à interface `Ecra` do jogo. Usa para integrar código que não controlas.

**Singleton** garante uma só instância: o registo de recordes. Usa com moderação, porque estado global dificulta testes.

## Exemplo: Strategy e State nos monstros

O movimento dos monstros usa Strategy, como na página de [Java](https://resumos.rgo.pt/cadeiras/ldts/padroes-desenho/java-orientado-objetos/):

```
Comportamento zigzag = new AndarEmZigZag();
Comportamento perseguir = new PerseguirHeroi(heroi);
Monstro m1 = new Monstro(new Posicao(5, 5), zigzag);
Monstro m2 = new Monstro(new Posicao(8, 2), perseguir);
```

Quando o nível aperta, o estado do monstro muda a estratégia por dentro:

```
public class MonstroAlerta implements EstadoMonstro {
    public Comportamento comportamento(Heroi heroi) {
        return new PerseguirHeroi(heroi);
    }
}
```

O `Monstro` pede ao seu estado o comportamento atual. Calmo devolve passeio, alerta devolve perseguição:

![Diagrama com Monstro no centro, EstadoCalmo e EstadoAlerta a devolverem o Comportamento correspondente.](https://resumos.rgo.pt/cadeiras/ldts/padroes-desenho/figura-1.svg)

O `switch` sobre o estado desapareceu, e um estado novo é uma classe nova. Troca a estratégia em tempo de execução e vê a diferença:

```java
interface Comportamento {
    String mover();
}

class AndarEmZigZag implements Comportamento {
    public String mover() { return "ziguezagueia"; }
}

class PerseguirHeroi implements Comportamento {
    public String mover() { return "persegue o heroi"; }
}

class Monstro {
    private Comportamento comportamento;

    Monstro(Comportamento comportamento) {
        this.comportamento = comportamento;
    }

    void setComportamento(Comportamento comportamento) {
        this.comportamento = comportamento;
    }

    String agir() {
        return comportamento.mover();
    }
}

public class Main {
    public static void main(String[] args) {
        Monstro monstro = new Monstro(new AndarEmZigZag());
        System.out.println("nivel facil: " + monstro.agir());
        monstro.setComportamento(new PerseguirHeroi());
        System.out.println("nivel dificil: " + monstro.agir());
    }
}
```

A saída mostra `nivel facil: ziguezagueia` e `nivel dificil: persegue o heroi`. Nenhuma classe do monstro foi editada: a variação vive nos objetos de comportamento.

## Exemplo: Observer na pontuação

A pontuação observa cada monstro sem os monstros saberem dela:

```
monstro.adicionarObservador(pontuacao);
// ... quando o monstro cai:
observadores.forEach(o -> o.notificar(100));
```

Adicionar um contador de mortes ou um efeito sonoro é registar mais um observador:

![Grafo com Monstro a notificar Pontuacao, Mortes e Som, sem setas de volta.](https://resumos.rgo.pt/cadeiras/ldts/padroes-desenho/figura-2.svg)

Nenhum monstro muda, porque nenhum monstro conhece os observadores: é o desacoplamento que o padrão promete.

[Vídeo: Observer Design Pattern (Derek Banas)](https://www.youtube.com/watch?v=wiQdrH2YpT4)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=wiQdrH2YpT4)

Como escolher na prova

Pergunta o que varia: algoritmos que se trocam é Strategy, comportamento que depende de estado é State, notificações a vários interessados é Observer, pedidos como objetos é Command, criação com lógica é Factory. O nome do padrão descreve a solução, não o problema.
