Médio TypeScript

Relatório com Template Method

Enunciado

Implemente uma classe abstrata GeradorRelatorio com o método concreto gerar() que chama os métodos abstratos cabecalho(), corpo() e rodape(), todos retornando string. Crie duas subclasses: RelatorioPDF e RelatorioHTML, que retornam textos diferentes para cada parte. O método gerar() deve juntar as três partes com quebras de linha e imprimir o resultado.

Requisitos

  • GeradorRelatorio deve ser abstrata e ter o método concreto gerar().
  • As subclasses devem implementar os três métodos abstratos.
  • A saída deve conter as três partes separadas por \n.

Código inicial

abstract class GeradorRelatorio {
  gerar(): void {
    // chame os métodos abstratos e imprima
  }

  protected abstract cabecalho(): string;
  protected abstract corpo(): string;
  protected abstract rodape(): string;
}

// Implemente RelatorioPDF e RelatorioHTML

Saída esperada

=== PDF ===
Conteúdo do PDF
--- Fim PDF ---
=== HTML ===
<div>Conteúdo HTML</div>
<!-- Fim HTML -->
Ver dica

No método gerar(), use console.log com template string e \n para separar as partes. Cada subclasse retorna strings diferentes.

Mostrar solução
abstract class GeradorRelatorio {
  gerar(): void {
    // Template Method: define a ordem das etapas
    const resultado = `${this.cabecalho()}\n${this.corpo()}\n${this.rodape()}`;
    console.log(resultado);
  }

  protected abstract cabecalho(): string;
  protected abstract corpo(): string;
  protected abstract rodape(): string;
}

class RelatorioPDF extends GeradorRelatorio {
  protected cabecalho(): string {
    return "=== PDF ===";
  }

  protected corpo(): string {
    return "Conteúdo do PDF";
  }

  protected rodape(): string {
    return "--- Fim PDF ---";
  }
}

class RelatorioHTML extends GeradorRelatorio {
  protected cabecalho(): string {
    return "=== HTML ===";
  }

  protected corpo(): string {
    return "<div>Conteúdo HTML</div>";
  }

  protected rodape(): string {
    return "<!-- Fim HTML -->";
  }
}

new RelatorioPDF().gerar();
new RelatorioHTML().gerar();

Passo a passo

  1. A classe abstrata GeradorRelatorio define o método concreto gerar(), que é o Template Method.
  2. Dentro de gerar(), chamamos this.cabecalho(), this.corpo() e this.rodape() na ordem correta, separando por \n.
  3. Os três métodos são declarados como abstract, sem corpo, forçando as subclasses a implementá-los.
  4. RelatorioPDF implementa cada método retornando strings típicas de PDF.
  5. RelatorioHTML implementa cada método retornando strings HTML.
  6. No final, criamos instâncias e chamamos gerar(), que executa o algoritmo definido na base.

Por que funciona

O Template Method fixa a estrutura do algoritmo na classe abstrata, mas delega partes variáveis para as subclasses. Assim, a sequência de geração do relatório é sempre a mesma, mas o conteúdo se adapta ao formato.

Erros comuns

  • Declarar gerar() como abstrato: aí não haveria implementação do esqueleto e o padrão se perderia.
  • Esquecer de implementar um dos métodos abstratos: erro de compilação.
  • Usar private nos métodos abstratos: eles precisam ser acessíveis na subclasse, então use protected ou public.

Outra forma de resolver

Poderia usar uma interface com os três métodos e uma função externa que os chama. Mas a classe abstrata mantém a lógica de composição junto com o contrato, o que é mais coeso.

Saída esperada

=== PDF ===
Conteúdo do PDF
--- Fim PDF ---
=== HTML ===
<div>Conteúdo HTML</div>
<!-- Fim HTML -->