Bridge Pattern là một mẫu thiết kế thuộc nhóm Structural Patterns (mẫu cấu trúc), được sử dụng để tách rời phần trừu tượng (abstraction) của một lớp khỏi phần triển khai (implementation) của nó, nhằm giúp chúng có thể phát triển độc lập với nhau. Mẫu thiết kế này đặc biệt hữu ích khi bạn cần thay đổi hoặc mở rộng cả phần trừu tượng và phần triển khai mà không làm ảnh hưởng đến nhau.
Mục tiêu chính của Bridge Pattern là tách biệt phần giao diện (abstraction) với phần thực thi (implementation), giúp giảm sự phụ thuộc lẫn nhau giữa các lớp và cho phép dễ dàng thay đổi hoặc mở rộng cả hai phần.
Bridge Pattern được sử dụng trong các trường hợp sau:
Cấu trúc của Bridge Pattern bao gồm các thành phần sau:
Bridge Pattern hoạt động bằng cách tách phần giao diện trừu tượng của một đối tượng khỏi phần thực thi của nó. Abstraction chứa một tham chiếu đến đối tượng Implementor, và Implementor chịu trách nhiệm thực thi các phương thức mà Abstraction yêu cầu. Abstraction không trực tiếp thực hiện các chức năng mà sẽ ủy quyền chúng cho Implementor.
Giả sử bạn có một hệ thống vẽ hình dạng, và bạn muốn vẽ các hình với các loại công cụ vẽ khác nhau (như bút vẽ, bút chì). Thay vì tạo các lớp con riêng biệt cho từng loại hình dạng và từng công cụ vẽ, bạn có thể sử dụng Bridge Pattern để tách biệt hình dạng và công cụ vẽ.
// Interface Implementor định nghĩa các phương thức vẽ public interface DrawingAPI { void drawCircle(double x, double y, double radius); } // Concrete Implementor A: API vẽ hình tròn bằng cách vẽ trên màn hình public class DrawingAPI1 implements DrawingAPI { @Override public void drawCircle(double x, double y, double radius) { System.out.println("Drawing circle at (" + x + ", " + y + ") with radius " + radius + " using API1."); } } // Concrete Implementor B: API vẽ hình tròn bằng cách vẽ trên console public class DrawingAPI2 implements DrawingAPI { @Override public void drawCircle(double x, double y, double radius) { System.out.println("Drawing circle at (" + x + ", " + y + ") with radius " + radius + " using API2."); } } // Lớp Abstraction: Hình tròn public abstract class Shape { protected DrawingAPI drawingAPI; protected Shape(DrawingAPI drawingAPI) { this.drawingAPI = drawingAPI; } public abstract void draw(); // Triển khai bởi các lớp con public abstract void resizeByPercentage(double pct); // Triển khai bởi các lớp con } // Refined Abstraction: Hình tròn cụ thể 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); } } // Sử dụng Bridge Pattern public class Main { public static void main(String[] args) { Shape circle1 = new CircleShape(1, 2, 3, new DrawingAPI1()); Shape circle2 = new CircleShape(5, 7, 11, new DrawingAPI2()); circle1.draw(); // Output: Drawing circle at (1.0, 2.0) with radius 3.0 using API1. circle2.draw(); // Output: Drawing circle at (5.0, 7.0) with radius 11.0 using API2. circle1.resizeByPercentage(50); // Tăng kích thước hình tròn lên 50% circle1.draw(); // Output: Drawing circle at (1.0, 2.0) with radius 4.5 using API1. } }
Trong ví dụ này:
Nhờ sử dụng Bridge Pattern, chúng ta có thể dễ dàng mở rộng hệ thống với các loại hình mới (chẳng hạn như hình vuông) hoặc các công cụ vẽ mới (chẳng hạn như vẽ 3D) mà không cần thay đổi mã nguồn hiện tại.
Bridge Pattern là một mẫu thiết kế mạnh mẽ giúp tách rời phần trừu tượng khỏi phần triển khai, cho phép chúng phát triển độc lập. Điều này làm giảm sự phụ thuộc giữa các lớp, giúp mã nguồn dễ bảo trì và mở rộng hơn. Mẫu thiết kế này đặc biệt hữu ích khi bạn cần xử lý một hệ thống với nhiều phần giao diện trừu tượng và nhiều cách triển khai, tránh việc tạo ra quá nhiều lớp con trong quá trình kế thừa. Tuy nhiên, bạn nên cẩn thận khi áp dụng để tránh làm tăng sự phức tạp không cần thiết cho hệ thống.