Bridge, Adapter e Proxy: Três padrões essenciais para o design de sistemas flexíveis

Padrão Bridge

O que é o padrão Bridge?

O padrão Bridge é um padrão de design estrutural que tem a intenção de “desacoplar uma abstração de sua implementação, de modo que as duas possam variar independentemente”. Parece complexo? Vamos simplificar: imagine que você tem um controle remoto de TV. A forma como o controle funciona é a abstração, e a marca ou modelo do controle é a implementação. Com o padrão Bridge, você pode alterar a forma como o controle funciona ou mudar a marca ou modelo sem que um interfira no outro.

Quando usar o padrão Bridge?

Recomendo a utilização do padrão Bridge quando você quer evitar um vínculo permanente entre a abstração e a implementação. Isso pode ser útil quando a implementação deve ser selecionada ou alterada em tempo de execução.

C#
using System;

// Abstração
abstract class Abstraction
{
    protected Implementor implementor;

    public Abstraction(Implementor implementor)
    {
        this.implementor = implementor;
    }

    public abstract void Operation();
}

// Implementação
interface Implementor
{
    void OperationImp();
}

// Implementação Concreta A
class ConcreteImplementorA : Implementor
{
    public void OperationImp()
    {
        Console.WriteLine("Implementação A sendo executada.");
    }
}

// Implementação Concreta B
class ConcreteImplementorB : Implementor
{
    public void OperationImp()
    {
        Console.WriteLine("Implementação B sendo executada.");
    }
}

// Abstração Refinada
class RefinedAbstraction : Abstraction
{
    public RefinedAbstraction(Implementor implementor) : base(implementor)
    {
    }

    public override void Operation()
    {
        Console.WriteLine("Abstração sendo executada.");
        implementor.OperationImp();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Cria as implementações concretas
        Implementor implementorA = new ConcreteImplementorA();
        Implementor implementorB = new ConcreteImplementorB();

        // Cria a abstração refinada associada com a implementação A
        Abstraction abstraction = new RefinedAbstraction(implementorA);
        abstraction.Operation();

        Console.WriteLine();

        // Altera a implementação associada à abstração para a implementação B
        abstraction.implementor = implementorB;
        abstraction.Operation();

        Console.ReadLine();
    }
}

// Fonte: ChatGPT

Neste exemplo, temos a abstração Abstraction que possui uma referência para a interface Implementor. As classes ConcreteImplementorA e ConcreteImplementorB são as implementações concretas da interface Implementor. A classe RefinedAbstraction é uma abstração refinada que estende a classe Abstraction. O programa principal cria as implementações concretas, associa a abstração refinada com a implementação A, executa a operação e, em seguida, altera a implementação para B e executa novamente a operação.

Padrão Adapter

O que é o padrão Adapter?

Agora vamos falar sobre o padrão Adapter. Ele é um padrão de design estrutural que permite que duas interfaces incompatíveis trabalhem juntas. É como um tradutor entre dois idiomas incompatíveis. Em outras palavras, o padrão Adapter cria uma ponte entre duas interfaces que de outra forma não poderiam trabalhar juntas devido a suas interfaces incompatíveis.

Quando usar o padrão Adapter?

Você deve considerar o uso do padrão Adapter quando quiser usar uma classe existente que seja incompatível com o restante do seu código. Ou quando quiser criar uma classe reutilizável que coopere com classes não relacionadas ou não previstas.

C#
using System;

// Interface existente
interface ITarget
{
    void Request();
}

// Classe existente
class Adaptee
{
    public void SpecificRequest()
    {
        Console.WriteLine("Método SpecificRequest da classe Adaptee sendo chamado.");
    }
}

// Adapter
class Adapter : ITarget
{
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee)
    {
        this.adaptee = adaptee;
    }

    public void Request()
    {
        Console.WriteLine("Adapter chamando o método SpecificRequest da classe Adaptee.");
        adaptee.SpecificRequest();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Cria a instância da classe Adaptee
        Adaptee adaptee = new Adaptee();

        // Cria o Adapter e passa a instância do Adaptee
        ITarget target = new Adapter(adaptee);

        // Chama o método Request do Adapter
        target.Request();

        Console.ReadLine();
    }
}

// Fonte: ChatGPT

Neste exemplo, temos a interface ITarget que define a interface esperada pelo cliente. A classe Adaptee é a classe existente que possui uma interface incompatível com ITarget. A classe Adapter implementa a interface ITarget e atua como um adaptador entre o cliente e a classe Adaptee. No programa principal, criamos uma instância de Adaptee, criamos um Adapter passando a instância do Adaptee e chamamos o método Request do Adapter, que internamente chama o método SpecificRequest da classe Adaptee.

Padrão Proxy

O que é o padrão Proxy?

Chegamos agora ao padrão Proxy. Esse padrão de design estrutural fornece um substituto ou espaço reservado para outro objeto para controlar o acesso a ele. É como um intermediário que pode adicionar funcionalidades extras ao objeto sem mudar sua interface.

Quando usar o padrão Proxy?

O padrão Proxy é útil quando você precisa controlar o acesso a um objeto, seja para adicionar uma camada de segurança, otimizar o desempenho, entre outros.

C#
using System;

// Interface do objeto real e do proxy
interface ISubject
{
    void Request();
}

// Objeto real
class RealSubject : ISubject
{
    public void Request()
    {
        Console.WriteLine("RealSubject: Processando a requisição.");
    }
}

// Proxy
class Proxy : ISubject
{
    private RealSubject realSubject;

    public void Request()
    {
        // Cria o objeto real sob demanda
        if (realSubject == null)
        {
            Console.WriteLine("Proxy: Criando uma instância do RealSubject.");
            realSubject = new RealSubject();
        }

        // Executa a requisição através do objeto real
        realSubject.Request();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Cria o proxy
        ISubject proxy = new Proxy();

        // Chama o método Request do proxy
        proxy.Request();

        Console.ReadLine();
    }
}

// Fonte: ChatGPT

Neste exemplo, temos a interface ISubject que define a interface tanto para o objeto real (RealSubject) quanto para o proxy (Proxy). A classe RealSubject representa o objeto real com a funcionalidade que desejamos controlar o acesso. O Proxy atua como um substituto do objeto real e controla o acesso a ele. No programa principal, criamos uma instância do Proxy e chamamos o método Request, que internamente verifica se o objeto real já foi criado ou não. Se não foi criado, o Proxy cria uma instância do RealSubject e em seguida realiza a requisição através do objeto real.

Como esses padrões ajudam no design de sistemas flexíveis

Os padrões de design Bridge, Adapter e Proxy contribuem para o desenvolvimento de sistemas flexíveis e adaptáveis. Cada um desses padrões oferece uma maneira diferente de garantir que as partes do seu sistema possam variar independentemente umas das outras.

Como esses padrões podem beneficiar o negócio

Em um contexto de negócios, a utilização desses padrões de design pode trazer vários benefícios, como maior flexibilidade, redução de custos com manutenção e evolução do sistema, além de permitir a integração com outros sistemas de forma mais fácil.

Conclusão

Para finalizar, os padrões de design são ferramentas poderosas que podem ajudar a criar sistemas mais flexíveis, de fácil manutenção e interoperáveis. Espero que este artigo tenha ajudado a esclarecer a importância dos padrões Bridge, Adapter e Proxy no design de sistemas. Lembre-se: a melhor prática é sempre aquela que melhor se adequa ao seu caso!

Esse conteúdo é parte do material disponibilizado para os participantes do meu grupo de estudos de Padrões de Projeto. Você quer participar desse grupo? Clique aqui e veja como funciona.

Dúvidas Frequentes

Qual a diferença entre os padrões Bridge, Adapter e Proxy?
A principal diferença é a finalidade de cada um deles. O padrão Bridge é usado para separar a abstração da implementação, o Adapter é utilizado para compatibilizar interfaces incompatíveis, e o Proxy controla o acesso a objetos.

Os padrões de design podem ajudar no desenvolvimento de software?
Sim, os padrões de design podem ajudar no desenvolvimento de software, tornando-o mais organizado, eficiente e fácil de manter.

Todos os sistemas precisam usar esses padrões?
Não necessariamente. O uso de padrões depende dos requisitos e complexidade do sistema.

O uso de padrões de design pode ter um impacto negativo?
Se usados incorretamente, os padrões de design podem tornar o sistema excessivamente complexo e difícil de entender. É importante usar os padrões de design de forma adequada.

Qual padrão de design devo usar?
Depende das necessidades do seu sistema. Cada padrão tem suas próprias vantagens e desvantagens, e a decisão de usar um padrão específico deve ser baseada nas necessidades específicas do seu sistema.

Elemar Júnior

Fundador e CEO da EximiaCo atua como tech trusted advisor ajudando empresas e pessoas a gerar mais resultados através da tecnologia.

Sessões de masterclass

Seja avisado de novos conteúdos

Gostou deste conteúdo? Então inscreva-se em nossa newsletter para receber notificações de novas publicações como essa:

Veja outros artigos relacionados

Aprenda a Simplificar seu Código Dominando o Padrão Chain of Responsibility

Em um mundo onde o desenvolvimento de software evolui a passos largos, se adaptar e dominar as melhores práticas é...

O que é o Padrão Iterator?

O padrão Iterator, amplamente usado em programação orientada a objetos, é um design pattern que permite aos desenvolvedores percorrer uma...

Integrando o padrão de projeto Interpreter na arquitetura de microservices: Como reduzir o acoplamento em sistemas distribuídos

Por que o acoplamento é um problema? A natureza do acoplamento Todos nós, no campo da tecnologia, já nos deparamos...

Crie sua conta

Preencha os dados a seguir para iniciar o seu cadastro no curso de Bridge, Adapter e Proxy: Três padrões essenciais para o design de sistemas flexíveis:

Crie sua conta

Preencha os dados a seguir para iniciar o seu cadastro no curso de Bridge, Adapter e Proxy: Três padrões essenciais para o design de sistemas flexíveis:

Bridge, Adapter e Proxy: Três padrões essenciais para o design de sistemas flexíveis

Crie sua conta

Preencha os dados a seguir para iniciar o seu cadastro no Grupo Intensivo de Estudos de Reputação e Marketing Pessoal:

Crie sua conta

Preencha os dados a seguir para iniciar o seu cadastro no curso de Bridge, Adapter e Proxy: Três padrões essenciais para o design de sistemas flexíveis:

Crie sua conta

Preencha os dados a seguir para iniciar o seu cadastro no Grupo Intensivo de Estudos de DDD do Jeito Certo:

Crie sua conta

Preencha os dados a seguir para iniciar o seu cadastro no Grupo Intensivo de Estudos de Padrões de Projeto:

Crie sua conta

Preencha os dados a seguir para iniciar o seu cadastro no Grupo Intensivo de Estudos de Algoritmos e Estruturas de Dados:

× Precisa de ajuda?