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:
- Abstracció (Abstraction): Defineix la interfície alta-nivell que utilitza el client.
- Abstracció Refinada (Refined Abstraction): Estén la interfície de l'abstracció.
- Implementador (Implementor): Defineix la interfície per a les classes d'implementació.
- 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
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.
Curs de Patrons de Disseny de Programari
Mòdul 1: Introducció als Patrons de Disseny
- Què són els Patrons de Disseny?
- Història i Origen dels Patrons de Disseny
- Classificació dels Patrons de Disseny
- Avantatges i Desavantatges d'Usar Patrons de Disseny
Mòdul 2: Patrons Creacionals
Mòdul 3: Patrons Estructurals
Mòdul 4: Patrons de Comportament
- Introducció als Patrons de Comportament
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Mòdul 5: Aplicació de Patrons de Disseny
- Com Seleccionar el Patró Adequat
- Exemples Pràctics d'Ús de Patrons
- Patrons de Disseny en Projectes Reals
- Refactorització Usant Patrons de Disseny
Mòdul 6: Patrons de Disseny Avançats
- Patrons de Disseny en Arquitectures Modernes
- Patrons de Disseny en Microserveis
- Patrons de Disseny en Sistemes Distribuïts
- Patrons de Disseny en Desenvolupament Àgil