Hôm nay, chúng ta sẽ cùng khám phá một trong những Design Pattern cấu trúc vô cùng mạnh mẽ: Bridge Design Pattern trong Java. Trong quá trình phát triển phần mềm, chúng ta thường xuyên đối mặt với các tình huống khi cần quản lý những hệ thống phân cấp (interface hierarchies) phức tạp, không chỉ ở phần giao diện (interfaces/abstractions) mà còn cả ở phần triển khai (implementations). Bridge Design Pattern chính là giải pháp tối ưu để giải quyết vấn đề này.
Bridge Design Pattern là gì
Giống như Adapter Pattern, Bridge Design Pattern là một trong những Structural Design Pattern. Theo định nghĩa của GoF (Gang of Four), Bridge Design Pattern là:
Tách rời một abstraction khỏi phần implementation của nó, để cả hai có thể thay đổi độc lập.
Nguyên tắc cốt lõi trong việc triển khai Bridge Design Pattern là ưu tiên Composition hơn là Inheritance. Điều này có nghĩa là thay vì một lớp con kế thừa hành vi từ lớp cha, chúng ta sẽ sử dụng một đối tượng của lớp khác (composition) để cung cấp hành vi đó. Sự kết hợp này tạo ra một “cầu nối” (bridge) giữa hai hệ thống phân cấp riêng biệt.
Ví dụ Bridge Design Pattern trong Java
Để nắm bắt rõ hơn Bridge Design Pattern, chúng ta hãy cùng xem xét một ví dụ thực tế.
Chúng ta sẽ sử dụng Bridge Design Pattern để tách rời các interface từ phần implementation của chúng. Bạn sẽ nhận thấy một “cầu nối” (bridge) giữa các interface Shape
và Color
, cùng với việc sử dụng composition trong việc triển khai Bridge Pattern. Điều này có nghĩa là lớp Shape
sẽ chứa một đối tượng Color
, thay vì kế thừa từ nó.
Dưới đây là mã Java cho các interface và lớp trừu tượng mà chúng ta sẽ xây dựng:
Đầu tiên là interface Color.java
đơn giản, định nghĩa hành vi áp dụng màu sắc:
Color.java
package com.journaldev.design.bridge;
public interface Color {
public void applyColor();
}
Tiếp theo là lớp trừu tượng Shape.java
. Đây chính là nơi chúng ta tạo ra “cầu nối” bằng cách sử dụng composition:
Shape.java
package com.journaldev.design.bridge;
public abstract class Shape {
//Composition - implementor
protected Color color;
//constructor with implementor as input argument
public Shape(Color c){
this.color=c;
}
abstract public void applyColor();
}
Trong lớp Shape
này, chúng ta khai báo một thuộc tính color
kiểu Color
và khởi tạo nó thông qua constructor. Đây chính là điểm mấu chốt: lớp Shape
không tự định nghĩa cách áp dụng màu, mà nó ủy quyền (delegate) hành vi này cho đối tượng color
mà nó chứa.
Chúng ta có các lớp triển khai cụ thể cho Shape
như Triangle
và Pentagon
dưới đây:
Triangle.java
package com.journaldev.design.bridge;
public class Triangle extends Shape{
public Triangle(Color c) {
super(c);
}
@Override
public void applyColor() {
System.out.print("Triangle filled with color ");
color.applyColor(); // Ủy quyền cho đối tượng color
}
}
Pentagon.java
package com.journaldev.design.bridge;
public class Pentagon extends Shape{
public Pentagon(Color c) {
super(c);
}
@Override
public void applyColor() {
System.out.print("Pentagon filled with color ");
color.applyColor(); // Ủy quyền cho đối tượng color
}
}
Các lớp Triangle
và Pentagon
kế thừa từ Shape
và triển khai phương thức applyColor()
. Quan trọng là chúng gọi phương thức color.applyColor()
để thực hiện việc tô màu, cho thấy sự ủy quyền hành vi cho đối tượng Color
đã được inject vào.
Giờ là các lớp triển khai cụ thể cho interface Color
:
RedColor.java
package com.journaldev.design.bridge;
public class RedColor implements Color{
public void applyColor(){
System.out.println("red.");
}
}
GreenColor.java
package com.journaldev.design.bridge;
public class GreenColor implements Color{
public void applyColor(){
System.out.println("green.");
}
}
Cuối cùng, hãy kiểm tra việc triển khai Bridge Pattern của chúng ta bằng một chương trình kiểm thử đơn giản:
BridgePatternTest.java
package com.journaldev.design.test;
import com.journaldev.design.bridge.GreenColor;
import com.journaldev.design.bridge.Pentagon;
import com.journaldev.design.bridge.RedColor;
import com.journaldev.design.bridge.Shape;
import com.journaldev.design.bridge.Triangle;
public class BridgePatternTest {
public static void main(String[] args) {
// Tạo một hình tam giác màu đỏ
Shape tri = new Triangle(new RedColor());
tri.applyColor();
// Tạo một hình ngũ giác màu xanh lá
Shape pent = new Pentagon(new GreenColor());
pent.applyColor();
}
}
Chương trình kiểm thử này minh họa rõ ràng cách chúng ta tạo ra các đối tượng Shape
và “kết nối” chúng với các đối tượng Color
mong muốn một cách linh hoạt. Triangle
không cần biết RedColor
là gì, và Pentagon
cũng không cần quan tâm đến GreenColor
. Chúng chỉ tương tác với interface Color
.
Kết quả của chương trình ví dụ trên sẽ là:
Triangle filled with color red.
Pentagon filled with color green.
Kết Luận
Tóm lại, Bridge Design Pattern là một công cụ mạnh mẽ trong hộp công cụ của mỗi lập trình viên, đặc biệt khi bạn cần tách rời một abstraction khỏi implementation của nó để cả hai có thể thay đổi và phát triển độc lập. Nguyên tắc cốt lõi là ưu tiên composition hơn kế thừa, tạo ra một “cầu nối” linh hoạt giữa hai hệ thống phân cấp. Với Bridge Pattern, bạn không chỉ tạo ra mã nguồn dễ bảo trì, dễ mở rộng hơn mà còn xây dựng các hệ thống linh hoạt, có khả năng thích ứng cao với các yêu cầu thay đổi trong tương lai.