Pular para o conteúdo
Estruturais

Facade

Fornece uma interface unificada e simplificada para um conjunto de interfaces em um subsistema, tornando o subsistema mais fácil de usar.

Intenção

Definir uma interface de nível mais alto que protege os clientes da complexidade de um subsistema, expondo apenas as operações que eles realmente precisam, delegando a orquestração de múltiplos componentes internos atrás de um único ponto de entrada.

Problema

Seu subsistema cresceu para muitas classes inter-relacionadas com sequências de inicialização intrincadas e dependências complexas. Clientes que precisam executar tarefas comuns têm que entender e coordenar numerosos objetos, levando a acoplamento forte e código frágil que quebra sempre que o subsistema evolui.

Solução

Crie uma classe facade que fornece uma API simples e de alto nível para os casos de uso mais comuns. A facade sabe quais classes do subsistema são responsáveis por cada requisição e delega adequadamente. Os clientes interagem com a facade em vez do subsistema diretamente, embora o subsistema continue acessível para cenários avançados.

Participantes

  • Facade -- fornece uma API simplificada e delega para os objetos do subsistema
  • Subsystem classes -- implementam a funcionalidade real; não têm conhecimento da facade
  • Client -- chama a facade em vez de manipular os objetos do subsistema diretamente

Vantagens

  • Reduz o acoplamento entre clientes e um subsistema complexo
  • Fornece uma configuração padrão conveniente para casos de uso comuns
  • Promove a independência do subsistema -- mudanças internas ficam atrás da facade
  • Não impede acesso direto ao subsistema quando controle avançado é necessário

Desvantagens

  • A facade pode virar um 'god object' se muitas responsabilidades se acumularem
  • Pode esconder funcionalidades úteis de nível mais baixo, tentando os desenvolvedores a contornar a facade
  • Adiciona uma camada extra que precisa ser mantida sincronizada com a evolução do subsistema

Analogia do mundo real

Um concierge de hotel atua como uma facade. Quando você pede para o concierge organizar um passeio pela cidade, ele coordena o serviço de táxi, a empresa de guia turístico, e o sistema de reserva de restaurante. Você interage com uma pessoa em vez de ligar para três serviços separados você mesmo.

Casos de uso

  • Simplificar um subsistema complexo de envio de e-mail (conexão SMTP, engine de template, tratamento de anexos) atrás de uma única chamada sendEmail()
  • Fornecer um método de ligar/desligar para um sistema de home theater com projetor, amplificador e player de streaming
  • Envolver um pipeline de geração de relatórios de múltiplas etapas (busca de dados, transformação, renderização em PDF) em um único método generateReport()
  • Oferecer uma API simplificada para um SDK complexo de terceiros
  • Encapsular etapas de migração de banco de dados (backup, diff de schema, migração, verificação) atrás de uma chamada migrate()

Exemplos de código

HomeTheaterFacade.java
final class Projector {
    void on() { System.out.println("Projector on"); }
    void setWidescreen() { System.out.println("Projector set to widescreen"); }
    void off() { System.out.println("Projector off"); }
}

final class Amplifier {
    void on() { System.out.println("Amplifier on"); }
    void setVolume(int level) { System.out.println("Volume set to " + level); }
    void off() { System.out.println("Amplifier off"); }
}

final class StreamingPlayer {
    void on() { System.out.println("Streaming player on"); }
    void play(String movie) { System.out.println("Playing "" + movie + """); }
    void stop() { System.out.println("Streaming player stopped"); }
    void off() { System.out.println("Streaming player off"); }
}

final class HomeTheaterFacade {
    private final Projector projector;
    private final Amplifier amp;
    private final StreamingPlayer player;

    HomeTheaterFacade(Projector projector, Amplifier amp, StreamingPlayer player) {
        this.projector = projector;
        this.amp = amp;
        this.player = player;
    }

    void watchMovie(String movie) {
        projector.on();
        projector.setWidescreen();
        amp.on();
        amp.setVolume(8);
        player.on();
        player.play(movie);
    }

    void endMovie() {
        player.stop();
        player.off();
        amp.off();
        projector.off();
    }
}

public class FacadeDemo {
    public static void main(String[] args) {
        HomeTheaterFacade theater = new HomeTheaterFacade(
                new Projector(), new Amplifier(), new StreamingPlayer());

        theater.watchMovie("Interstellar");
        theater.endMovie();
    }
}

Uma HomeTheaterFacade que envolve múltiplas classes de subsistema (projetor, amplificador, player de streaming) e expõe métodos simples watchMovie/endMovie.