Cleibson Gomes

Bridge Pattern em Java: Separando Abstração e Implementação

Entenda o Bridge Pattern, um padrão estrutural que desacopla abstração e implementação, com exemplos práticos em Java.

Introdução

O Bridge Pattern é um padrão de design estrutural que desacopla uma abstração de sua implementação, permitindo que ambas possam evoluir de forma independente. É especialmente útil em cenários onde as abstrações e implementações possuem muitas variações, evitando uma explosão de subclasses.

Neste post, vamos explorar o conceito do Bridge Pattern, suas vantagens e desvantagens, e implementar um exemplo prático em Java.


O que é o Bridge Pattern?

O Bridge Pattern foca em dividir a hierarquia em duas partes:

  1. Abstração: Define a interface de alto nível que o cliente utiliza.
  2. Implementação: Contém os detalhes concretos que podem variar.

Essas duas hierarquias são conectadas por meio de uma “ponte” (bridge), representada por uma referência que a abstração mantém para a implementação.


Quando usar o Bridge Pattern?

  • Quando você precisa dividir uma hierarquia em duas dimensões independentes.
  • Para evitar a explosão de subclasses devido a múltiplas combinações de funcionalidades.
  • Quando você deseja alterar a abstração e a implementação separadamente.

Exemplo Prático em Java

Vamos implementar o Bridge Pattern para um sistema de dispositivos (TV e rádio) controlados por controles remotos simples e avançados.


1. Criando a Interface Device

A interface Device define as operações que qualquer dispositivo deve implementar:

public interface Device {
    void turnOn();
    void turnOff();
    void setVolume(int volume);
    int getVolume();
}

2. Criando Implementações Concretas de Device

TV:

public class TV implements Device {
    private int volume;

    @Override
    public void turnOn() {
        System.out.println("TV is turned on");
    }

    @Override
    public void turnOff() {
        System.out.println("TV is turned off");
    }

    @Override
    public void setVolume(int volume) {
        this.volume = volume;
        System.out.println("TV volume set to " + this.volume);
    }

    @Override
    public int getVolume() {
        return volume;
    }
}

Rádio:

public class Radio implements Device {
    private int volume;

    @Override
    public void turnOn() {
        System.out.println("Radio is turned on");
    }

    @Override
    public void turnOff() {
        System.out.println("Radio is turned off");
    }

    @Override
    public void setVolume(int volume) {
        this.volume = volume;
        System.out.println("Radio volume set to " + this.volume);
    }

    @Override
    public int getVolume() {
        return volume;
    }
}

3. Criando a Classe Abstrata RemoteControl

A classe RemoteControl define operações comuns para todos os controles remotos:

public class RemoteControl {
    protected Device device;

    public RemoteControl(Device device) {
        this.device = device;
    }

    public void turnOn() {
        device.turnOn();
    }

    public void turnOff() {
        device.turnOff();
    }

    public void setVolume(int volume) {
        device.setVolume(volume);
    }
}

4. Criando uma Subclasse para Controle Avançado

O controle remoto avançado adiciona novas funcionalidades, como “mute”:

public class AdvancedRemoteControl extends RemoteControl {

    public AdvancedRemoteControl(Device device) {
        super(device);
    }

    public void mute() {
        System.out.println("Muting the device");
        device.setVolume(0);
    }
}

5. Criando o Cliente

No cliente, conectamos dispositivos aos controles remotos:

public class BridgePatternDemo {
    public static void main(String[] args) {
        // Criando dispositivos
        Device tv = new TV();
        Device radio = new Radio();

        // Usando controle remoto simples
        RemoteControl simpleRemote = new RemoteControl(tv);
        simpleRemote.turnOn();
        simpleRemote.setVolume(10);
        simpleRemote.turnOff();

        System.out.println();

        // Usando controle remoto avançado
        AdvancedRemoteControl advancedRemote = new AdvancedRemoteControl(radio);
        advancedRemote.turnOn();
        advancedRemote.setVolume(20);
        advancedRemote.mute();
        advancedRemote.turnOff();
    }
}

Saída do Programa:

Ao executar o código acima, você verá a seguinte saída:

TV is turned on
TV volume set to 10
TV is turned off

Radio is turned on
Radio volume set to 20
Muting the device
Radio is turned off

Vantagens e Desvantagens

Vantagens:

  • Desacoplamento: Separa a abstração da implementação, permitindo alterações independentes.
  • Flexibilidade: Facilita a adição de novas abstrações ou implementações sem modificar o código existente.
  • Redução de Subclasses: Evita explosões na hierarquia de classes.

Desvantagens:

  • Complexidade: Pode aumentar a complexidade do código inicial.
  • Sobrecarga: Para aplicações simples, pode ser uma solução desnecessária.

Quando evitar o Bridge Pattern?

  • Quando não há necessidade de separar abstrações e implementações.
  • Para sistemas simples, onde o padrão pode adicionar complexidade desnecessária.

Conclusão

O Bridge Pattern é uma solução poderosa para lidar com sistemas que possuem múltiplas dimensões de variação. Ele promove a flexibilidade e a extensibilidade, tornando o código mais fácil de manter e escalar.

Se você lida com cenários onde a abstração e a implementação precisam mudar frequentemente, o Bridge Pattern pode ser a solução ideal. Experimente e veja como ele se encaixa no seu projeto!


Gostou deste post? Continue acompanhando para mais conteúdos sobre padrões de design e desenvolvimento em Java!

blog@nosbielc.com

Made with ❤️ in Quebec, CA.