Médio Java

Template Method para preparo de bebidas

Enunciado

Implemente uma classe abstrata BebidaQuente com o template method preparar() que executa na ordem: ferverAgua(), preparar() e servir(). Os métodos ferverAgua() e servir() são concretos e imprimem mensagens genéricas. O método preparar() é abstrato. Crie as subclasses Cha e Cafe que implementam preparar() com mensagens específicas. No main, prepare um chá e um café.

Requisitos

  • A classe BebidaQuente deve ser abstrata e conter o método preparar() como final.
  • ferverAgua() e servir() devem ser concretos e reutilizados.
  • Cha e Cafe devem implementar preparar() com mensagens distintas.
  • A saída deve mostrar a sequência correta para cada bebida.

Código inicial

abstract class BebidaQuente {
    public final void preparar() {
        // chame os métodos na ordem correta
    }

    protected void ferverAgua() {
        System.out.println("Fervendo água...");
    }

    protected abstract void prepararBebida();

    protected void servir() {
        System.out.println("Servindo na xícara.");
    }
}

class Cha extends BebidaQuente {
    @Override
    protected void prepararBebida() {
        // implemente
    }
}

class Cafe extends BebidaQuente {
    @Override
    protected void prepararBebida() {
        // implemente
    }
}

public class Main {
    public static void main(String[] args) {
        BebidaQuente cha = new Cha();
        cha.preparar();
        System.out.println("---");
        BebidaQuente cafe = new Cafe();
        cafe.preparar();
    }
}

Saída esperada

Fervendo água...
Preparando o chá...
Servindo na xícara.
---
Fervendo água...
Preparando o café...
Servindo na xícara.
Ver dica

No método preparar(), chame ferverAgua(), depois prepararBebida() e por fim servir(). Nas subclasses, implemente prepararBebida() com a mensagem específica.

Mostrar solução
abstract class BebidaQuente {
    // Template method: define a ordem dos passos
    public final void preparar() {
        ferverAgua();
        prepararBebida();
        servir();
    }

    protected void ferverAgua() {
        System.out.println("Fervendo água...");
    }

    protected abstract void prepararBebida();

    protected void servir() {
        System.out.println("Servindo na xícara.");
    }
}

class Cha extends BebidaQuente {
    @Override
    protected void prepararBebida() {
        System.out.println("Preparando o chá...");
    }
}

class Cafe extends BebidaQuente {
    @Override
    protected void prepararBebida() {
        System.out.println("Preparando o café...");
    }
}

public class Main {
    public static void main(String[] args) {
        BebidaQuente cha = new Cha();
        cha.preparar();
        System.out.println("---");
        BebidaQuente cafe = new Cafe();
        cafe.preparar();
    }
}

Passo a passo

  1. BebidaQuente é abstrata e contém o método preparar() marcado como final, impedindo que subclasses alterem a ordem.
  2. ferverAgua() e servir() são concretos e fornecem passos comuns.
  3. prepararBebida() é abstrato e será implementado por cada subclasse.
  4. Cha e Cafe sobrescrevem prepararBebida() com suas mensagens específicas.
  5. No main, criamos instâncias e chamamos preparar(), que executa a sequência definida.
  6. A saída mostra a ordem correta: ferver, preparar e servir.

Por que funciona

O Template Method define o esqueleto do algoritmo na superclasse, mas delega partes variáveis para as subclasses. O uso de final garante que a estrutura não seja modificada. Isso é um exemplo clássico de inversão de controle e reuso.

Erros comuns

  • Não marcar preparar() como final: subclasses poderiam sobrescrever e quebrar a sequência.
  • Esquecer de implementar prepararBebida(): erro de compilação.
  • Colocar a lógica específica na classe base: perderia a generalização.

Outra forma de resolver

Poderia usar uma interface com métodos default para os passos comuns, mas classes abstratas permitem estado compartilhado e métodos protegidos.

Saída esperada

Fervendo água...
Preparando o chá...
Servindo na xícara.
---
Fervendo água...
Preparando o café...
Servindo na xícara.