CodeGym /Blogue Java /Random-PT /Padrão de projeto de ponte
John Squirrels
Nível 41
San Francisco

Padrão de projeto de ponte

Publicado no grupo Random-PT
Oi! Agora continuamos a nos aprofundar em um tópico útil extenso e super importante: padrões de projeto. Hoje vamos falar sobre o padrão de ponte. Como outros padrões, o padrão de ponte serve para resolver problemas típicos que um desenvolvedor encontra ao projetar a arquitetura de software. Hoje vamos estudar os recursos desse padrão e descobrir como usá-lo.

Qual é o padrão da ponte?

O padrão de ponte é um padrão de projeto estrutural. Em outras palavras, sua principal tarefa é criar uma estrutura completa de classes e objetos. Uma ponte faz isso dividindo uma ou mais classes em hierarquias separadas: abstração e implementação . Uma mudança na funcionalidade em uma hierarquia não acarreta uma mudança na outra. Tudo bem, mas essa definição é muito ampla e não responde à pergunta mais importante: "Qual é o padrão da ponte?" Acho que será mais fácil para você entender sua aplicação prática. Então, vamos criar um cenário clássico para o padrão de ponte. Temos uma Shapeclasse abstrata, que representa uma figura geométrica genérica:
  • Shape.java

    
    public abstract class Shape {
       public abstract void draw();
    }
    

    Quando decidirmos adicionar formas como triângulos e retângulos, faremos com que eles herdem a Shapeclasse:

  • Rectangle.java:

    
    public class Rectangle extends Shape {
       @Override
       public void draw() {
           System.out.println("Drawing rectangle");
       }
    }
    
  • Triangle.java:

    
    public class Triangle extends Shape {
       @Override
       public void draw() {
           System.out.println("Drawing triangle");
       }
    }
    
Tudo parece simples até o momento em que introduzimos o conceito de cor. Ou seja, cada forma terá sua própria cor, e a funcionalidade do draw()método dependerá dessa cor. Para ter diferentes implementações do draw()método, então precisamos criar uma classe para cada combinação forma-cor. Se tivermos três cores, precisaremos de seis classes: TriangleBlack, TriangleGreen, TriangleRed, e . Seis classes não é um problema tão grande. Mas! Se precisarmos adicionar uma nova forma ou cor, o número de classes aumentará exponencialmente. Como sair dessa situação? Armazenar cores em um campo e enumerar todas as opções usando instruções condicionais não é a melhor solução. Uma boa solução é mover a cor para uma interface separadaRectangleBlackRectangleGreenRectangleRed. Dito e feito: vamos criar uma Colorinterface com três implementações: BlackColor, GreenColore RedColor:
  • Color.java:

    
    public interface Color {
       void fillColor();
    }
    
  • BlackColor.java:

    
    public class BlackColor implements Color {
       @Override
       public void fillColor() {
           System.out.println("Filling in black color");
       }
    }
    
  • GreenColor.java

    
    public class GreenColor implements Color {
       @Override
       public void fillColor() {
           System.out.println("Filling in green color");
       }
    }
    
  • RedColor.java

    
    public class RedColor implements Color {
       @Override
       public void fillColor() {
           System.out.println("Filling in red color");
       }
    }
    

    Agora adicionamos um Colorcampo à Shapeclasse. Obteremos seu valor no construtor.

  • shape.java:

    
    public abstract class Shape {
       protected Color color;
      
       public Shape(Color color) {
           this.color = color;
       }
    
       public abstract void draw();
    }
    

    Usaremos a colorvariável em Shapeimplementações. Isso significa que as formas agora podem usar a funcionalidade da Colorinterface.

  • Retângulo.java

    
    public class Rectangle extends Shape {
    
       public Rectangle(Color color) {
           super(color);
       }
    
       @Override
       public void draw() {
           System.out.println("Drawing rectangle");
           color.fillColor();
       }
    }
    
Ta-da! Agora podemos criar diferentes cores e formas ad infinitum, e o número de classes aumentará apenas linearmente. O Color colorcampo é uma ponte que conecta duas hierarquias de classes separadas.

Como construir uma ponte: abstração e implementação

Vejamos um diagrama de classes que descreve o padrão de ponte: Apresentando o padrão de projeto de ponte - 2Aqui você pode ver duas estruturas independentes que podem ser modificadas sem afetar a funcionalidade uma da outra. No nosso caso:
  • Abstração é a Shapeclasse
  • RefinedAbstraction são as classes TriangleeRectangle
  • Implementador é a Colorinterface
  • ConcreteImplementor é o BlackColor, GreenColore RedColoras classes.
A Shapeclasse é uma abstração — um mecanismo para gerenciar o preenchimento de formas com várias cores, que delega para a Colorinterface (Implementor). As classes Trianglee Rectanglesão classes concretas que utilizam o mecanismo disponibilizado pela Shapeclasse. BlackColor, GreenColore RedColorsão implementações concretas na hierarquia de Implementação.

Onde usar o padrão de ponte

Um grande benefício de usar esse padrão é que você pode fazer alterações nas classes funcionais em uma hierarquia sem quebrar a lógica da outra. Além disso, essa abordagem ajuda a reduzir o acoplamento entre as classes. O principal requisito ao usar esse padrão é "siga as instruções" — não ignore nenhuma delas! Para isso, vamos descobrir as situações em que você definitivamente deve usar o padrão bridge:
  1. Se você precisar expandir o número de entidades com base em combinações de dois conceitos (por exemplo, formas e cores).

  2. Se você deseja dividir uma classe grande que não atende ao princípio de responsabilidade única em classes menores com funcionalidade restrita.

  3. Se for necessário fazer alterações na lógica de determinadas entidades enquanto o programa estiver em execução.

  4. Se for necessário ocultar uma implementação dos clientes da classe ou biblioteca.

Ao usar este padrão, lembre-se sempre de que ele adiciona entidades adicionais ao seu código — pode não fazer sentido usá-lo em um projeto onde há apenas uma forma e uma ou duas cores possíveis.

Prós e contras do padrão

Como outros padrões, uma ponte tem vantagens e desvantagens. Vantagens do padrão de ponte:
  1. Melhora a escalabilidade do código — você pode adicionar funcionalidade sem medo de quebrar algo em outra parte do programa.
  2. Reduz o número de subclasses quando o número de entidades seria baseado em combinações de dois conceitos (por exemplo, formas e cores).
  3. Torna possível trabalhar separadamente em duas hierarquias distintas — Abstração e Implementação. Dois desenvolvedores diferentes podem fazer alterações sem se aprofundar nos detalhes do código um do outro.
  4. Reduz o acoplamento entre as classes — o único lugar onde as duas classes são acopladas é a ponte (ou seja, o Color colorcampo).
Desvantagens do padrão de ponte:
  1. Dependendo da situação específica e da estrutura geral de um projeto, isso pode afetar negativamente o desempenho de um programa (por exemplo, se você precisar inicializar mais objetos).
  2. Isso torna o código menos legível devido à necessidade de alternar entre as duas classes.

Diferença do padrão de estratégia

O padrão de ponte é frequentemente confundido com outro padrão de projeto — estratégia. Ambos usam composição (embora tenhamos usado agregação no exemplo com figuras e cores, o padrão Bridge também pode usar composição), delegando trabalho a outros objetos. Mas há uma diferença entre eles, e é enorme. O padrão de estratégia é um padrão de comportamento: resolve problemas completamente diferentes. A estratégia permite que os algoritmos sejam trocados, enquanto a ponte separa uma abstração de implementações para escolher entre diferentes implementações. Em outras palavras, ao contrário de uma estratégia, uma ponte se aplica a entidades inteiras ou estruturas hierárquicas. O padrão de ponte pode ser uma boa arma no arsenal de um desenvolvedor. O principal é identificar as situações em que vale a pena usá-lo e reconhecer quando algum outro padrão é adequado.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION