Mẫu cầu là gì?
Mẫu cầu là một mẫu thiết kế cấu trúc. Nghĩa là, nhiệm vụ chính của nó là tạo ra một cấu trúc hoàn chỉnh của các lớp và đối tượng. Bridge giải quyết vấn đề này bằng cách tách một hoặc nhiều lớp thành các hệ thống phân cấp riêng biệt - trừu tượng hóa và triển khai . Sự thay đổi chức năng trong một hệ thống phân cấp không kéo theo những thay đổi trong hệ thống phân cấp khác. Mọi thứ có vẻ rõ ràng, nhưng trên thực tế, định nghĩa này nghe có vẻ rất rộng và không trả lời được câu hỏi chính: “Mẫu cầu là gì?” Tôi nghĩ điều này sẽ dễ dàng hơn cho bạn trong thực tế. Hãy lập ngay một ví dụ cổ điển cho mẫu Cầu. Chúng ta có một lớp trừu tượngShape
thường mô tả một hình hình học:
-
Shape.java
public abstract class Shape { public abstract void draw(); }
Khi chúng tôi quyết định thêm hình tam giác và hình chữ nhật, chúng tôi sẽ kế thừa từ lớp
Shape
: -
Hình chữ nhật.java:
public class Rectangle extends Shape { @Override public void draw() { System.out.println("Drawing rectangle"); } }
-
Tam giác.java:
public class Triangle extends Shape { @Override public void draw() { System.out.println("Drawing triangle"); } }
draw()
. Để có các cách triển khai phương thức khác nhau draw()
, chúng ta cần tạo một lớp cho mỗi hình tương ứng với một màu. Nếu có ba màu thì có sáu lớp : TriangleBlack
, TriangleGreen
, TriangleRed
, RectangleBlack
và RectangleGreen
. RectangleRed
Sáu lớp không phải là vấn đề lớn. Nhưng! Nếu chúng ta cần thêm hình dạng hoặc màu sắc mới, số lượng lớp sẽ tăng theo cấp số nhân. Làm thế nào để thoát khỏi tình trạng này? Lưu trữ màu sắc trong một trường và thử các tùy chọn thông qua các điều kiện không phải là giải pháp tốt nhất. Một giải pháp tốt là hiển thị màu sắc trong một giao diện riêng . Nói sớm hơn làm: hãy tạo một giao diện Color
và ba cách triển khai của nó - BlackColor
, GreenColor
và RedColor
:
-
Màu.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"); } }
Bây giờ hãy thêm một trường loại
Color
vào lớpShape
- chúng ta sẽ nhận giá trị của nó trong hàm tạo. -
Hình dạng.java:
public abstract class Shape { protected Color color; public Shape(Color color) { this.color = color; } public abstract void draw(); }
color
Chúng tôi sẽ sử dụng biến trong quá trình triển khaiShape
. Điều này có nghĩa là bây giờ các hình dạng có thể sử dụng chức năng của giao diệnColor
. -
Hình chữ nhật.java
public class Rectangle extends Shape { public Rectangle(Color color) { super(color); } @Override public void draw() { System.out.println("Drawing rectangle"); color.fillColor(); } }
Color color
là cầu nối kết nối hai hệ thống phân cấp lớp riêng biệt.
Thiết bị cầu nối: trừu tượng hóa và triển khai là gì
Chúng ta hãy xem sơ đồ lớp mô tả mẫu Cầu: Tại đây bạn có thể thấy hai cấu trúc độc lập có thể được sửa đổi mà không ảnh hưởng đến chức năng của nhau. Trong trường hợp của chúng tôi đó là:- Trừu tượng - lớp
Shape
; - RefinedAbstraction - các lớp
Triangle
,Rectangle
; - Người triển khai - giao diện
Color
; - ConcreteImplementor - các lớp
BlackColor
vàGreenColor
.RedColor
Shape
đại diện cho một Trừu tượng - một cơ chế kiểm soát việc tô màu các hình dạng bằng các màu khác nhau, ủy quyền Triển khai cho giao diện Color
. Lớp Triangle
là Rectangle
các đối tượng thực sử dụng cơ chế do lớp cung cấp Shape
. BlackColor
và GreenColor
- RedColor
các triển khai cụ thể trong nhánh Triển khai. Chúng thường được gọi là một nền tảng.
Mẫu cầu được sử dụng ở đâu?
Một lợi thế rất lớn của việc sử dụng mẫu này là bạn có thể thực hiện các thay đổi đối với chức năng của các lớp trong một nhánh mà không vi phạm logic của nhánh khác. Cách tiếp cận này cũng giúp giảm bớt sự ghép nối của các lớp chương trình. Điều kiện chính để sử dụng các mẫu là “làm theo hướng dẫn”: đừng dán chúng vào bất cứ đâu! Trên thực tế, hãy tìm hiểu xem bạn chắc chắn cần sử dụng Bridge trong những trường hợp nào:-
Nếu cần mở rộng số lượng thực thể theo hai hướng (hình dạng hình học, màu sắc).
-
Nếu bạn muốn chia một lớp lớn không đáp ứng nguyên tắc Trách nhiệm duy nhất thành các lớp nhỏ hơn với chức năng cấu hình hẹp.
-
Nếu có thể cần thực hiện các thay đổi đối với logic hoạt động của một số thực thể nhất định trong khi chương trình đang chạy.
-
Nếu cần, hãy ẩn việc triển khai khỏi các máy khách lớp (thư viện).
Ưu và nhược điểm của mẫu
Giống như các mẫu khác, Bridge có cả ưu điểm và nhược điểm. Lợi ích của Cầu:- Cải thiện khả năng mở rộng mã - bạn có thể thêm chức năng mà không sợ làm hỏng nội dung nào đó trong phần khác của chương trình.
- Giảm số lượng lớp con - hoạt động khi cần mở rộng số lượng thực thể theo hai hướng (ví dụ: số lượng hình dạng và số lượng màu sắc).
- Giúp có thể hoạt động riêng biệt trên hai nhánh Trừu tượng và Triển khai độc lập - điều này có thể được thực hiện bởi hai nhà phát triển khác nhau mà không cần đi sâu vào chi tiết về mã của nhau.
- Giảm sự ghép nối của các lớp - nơi duy nhất hai lớp được kết nối với nhau là cầu nối (trường
Color color
).
- Tùy thuộc vào tình hình cụ thể và cấu trúc của toàn bộ dự án, có thể có tác động tiêu cực đến năng suất của chương trình (ví dụ: nếu cần khởi tạo nhiều đối tượng hơn).
- Làm phức tạp khả năng đọc mã do cần phải điều hướng giữa các lớp.
GO TO FULL VERSION