Introducció

El patró de disseny Bridge és un patró estructural que té com a objectiu desacoblar una abstracció de la seva implementació perquè ambdues puguin variar independentment. Aquest patró és especialment útil quan es vol evitar una explosió combinatòria de classes derivades, permetent una major flexibilitat i escalabilitat en el disseny del sistema.

Objectius del Patró Bridge

  • Desacoblar l'abstracció de la implementació: Permet que l'abstracció i la implementació evolucionin independentment.
  • Reduir la complexitat: Evita la creació de múltiples subclasses per cada combinació possible d'abstracció i implementació.
  • Facilitar l'extensibilitat: Facilita l'extensió de les jerarquies d'abstracció i implementació sense afectar l'altra.

Estructura del Patró Bridge

El patró Bridge es compon de quatre components principals:

  1. Abstracció (Abstraction): Defineix la interfície alta-nivell que utilitza el client.
  2. Abstracció Refinada (Refined Abstraction): Estén la interfície de l'abstracció.
  3. Implementador (Implementor): Defineix la interfície per a les classes d'implementació.
  4. Implementació Concreta (Concrete Implementor): Proporciona una implementació concreta de la interfície de l'implementador.

Diagrama UML

Abstraction
+ operation(): void
  - implementor: Implementor

RefinedAbstraction
+ operation(): void

Implementor
+ operationImpl(): void

ConcreteImplementorA
+ operationImpl(): void

ConcreteImplementorB
+ operationImpl(): void

Exemple Pràctic

Escenari

Suposem que estem desenvolupant una aplicació de dibuix que pot dibuixar formes com cercles i quadrats. A més, aquestes formes es poden dibuixar en diferents plataformes com Windows i Linux.

Implementació

Interfície Implementor

// Implementor
public interface DrawingAPI {
    void drawCircle(double x, double y, double radius);
}

Implementacions Concretes

// ConcreteImplementorA
public class WindowsDrawingAPI implements DrawingAPI {
    @Override
    public void drawCircle(double x, double y, double radius) {
        System.out.println("Drawing circle on Windows at (" + x + ", " + y + ") with radius " + radius);
    }
}

// ConcreteImplementorB
public class LinuxDrawingAPI implements DrawingAPI {
    @Override
    public void drawCircle(double x, double y, double radius) {
        System.out.println("Drawing circle on Linux at (" + x + ", " + y + ") with radius " + radius);
    }
}

Abstracció

// Abstraction
public abstract class Shape {
    protected DrawingAPI drawingAPI;

    protected Shape(DrawingAPI drawingAPI) {
        this.drawingAPI = drawingAPI;
    }

    public abstract void draw(); // low-level
    public abstract void resizeByPercentage(double pct); // high-level
}

Abstracció Refinada

// RefinedAbstraction
public class CircleShape extends Shape {
    private double x, y, radius;

    public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
        super(drawingAPI);
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    @Override
    public void draw() {
        drawingAPI.drawCircle(x, y, radius);
    }

    @Override
    public void resizeByPercentage(double pct) {
        radius *= (1.0 + pct / 100.0);
    }
}

Client

public class BridgePatternDemo {
    public static void main(String[] args) {
        Shape[] shapes = new Shape[] {
            new CircleShape(1, 2, 3, new WindowsDrawingAPI()),
            new CircleShape(5, 7, 11, new LinuxDrawingAPI())
        };

        for (Shape shape : shapes) {
            shape.draw();
            shape.resizeByPercentage(10);
            shape.draw();
        }
    }
}

Sortida Esperada

Drawing circle on Windows at (1.0, 2.0) with radius 3.0
Drawing circle on Windows at (1.0, 2.0) with radius 3.3
Drawing circle on Linux at (5.0, 7.0) with radius 11.0
Drawing circle on Linux at (5.0, 7.0) with radius 12.1

Exercici Pràctic

Enunciat

Implementa el patró Bridge per a una aplicació que pugui dibuixar rectangles en diferents plataformes (Windows i Linux). Defineix les classes necessàries seguint l'exemple anterior.

Solució

Interfície Implementor

public interface DrawingAPI {
    void drawRectangle(double x, double y, double width, double height);
}

Implementacions Concretes

public class WindowsDrawingAPI implements DrawingAPI {
    @Override
    public void drawRectangle(double x, double y, double width, double height) {
        System.out.println("Drawing rectangle on Windows at (" + x + ", " + y + ") with width " + width + " and height " + height);
    }
}

public class LinuxDrawingAPI implements DrawingAPI {
    @Override
    public void drawRectangle(double x, double y, double width, double height) {
        System.out.println("Drawing rectangle on Linux at (" + x + ", " + y + ") with width " + width + " and height " + height);
    }
}

Abstracció

public abstract class Shape {
    protected DrawingAPI drawingAPI;

    protected Shape(DrawingAPI drawingAPI) {
        this.drawingAPI = drawingAPI;
    }

    public abstract void draw();
    public abstract void resizeByPercentage(double pct);
}

Abstracció Refinada

public class RectangleShape extends Shape {
    private double x, y, width, height;

    public RectangleShape(double x, double y, double width, double height, DrawingAPI drawingAPI) {
        super(drawingAPI);
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        drawingAPI.drawRectangle(x, y, width, height);
    }

    @Override
    public void resizeByPercentage(double pct) {
        width *= (1.0 + pct / 100.0);
        height *= (1.0 + pct / 100.0);
    }
}

Client

public class BridgePatternDemo {
    public static void main(String[] args) {
        Shape[] shapes = new Shape[] {
            new RectangleShape(1, 2, 3, 4, new WindowsDrawingAPI()),
            new RectangleShape(5, 7, 11, 13, new LinuxDrawingAPI())
        };

        for (Shape shape : shapes) {
            shape.draw();
            shape.resizeByPercentage(10);
            shape.draw();
        }
    }
}

Sortida Esperada

Drawing rectangle on Windows at (1.0, 2.0) with width 3.0 and height 4.0
Drawing rectangle on Windows at (1.0, 2.0) with width 3.3 and height 4.4
Drawing rectangle on Linux at (5.0, 7.0) with width 11.0 and height 13.0
Drawing rectangle on Linux at (5.0, 7.0) with width 12.1 and height 14.3

Conclusió

El patró Bridge és una solució elegant per desacoblar les abstraccions de les seves implementacions, permetent una major flexibilitat i escalabilitat en el disseny del sistema. Aquest patró és especialment útil en situacions on es preveu una gran varietat de combinacions d'abstraccions i implementacions.

© Copyright 2024. Tots els drets reservats