Nếu bạn muốn tìm hiểu các Design Pattern (Mẫu thiết kế) và đang tìm kiếm một hướng dẫn toàn diện bao gồm tất cả các mẫu thiết kế trong lập trình hướng đối tượng thì đây chính là bài viết mà các bạn không nên bỏ qua.

Hệ thống các mẫu design pattern được chia thành 3 nhóm, được phân loại theo mục đích sử dụng, gồm:

  • Nhóm Creational

  • Nhóm Structural

  • Nhóm Behavioral

I. Nhóm Creational

Creational design patterns trong Java là một nhóm các mẫu thiết kế tập trung vào việc khởi tạo object. Giúp object linh hoạt hơn và ít tight-coupling (liên kết ràng buộc) hơn với client code. 

Các Creational design patterns thúc đẩy việc tái sử dụng code, khả năng bảo trì và khả năng mở rộng, tạo điều kiện thuận lợi cho việc tạo các object theo cách hiệu quả và có khả năng kiểm soát nhằm đáp ứng các yêu cầu đa dạng của ứng dụng.

Dưới đây là danh sách các Creational design patterns phổ biến trong Java.

1. Factory Design pattern

Đây là một mẫu thiết kế rất hữu ích và được xem là một mẫu giúp tạo instance của các object trong Java. Nó cung cấp khả năng kiểm soát tốt hơn đối với quá trình tạo object sau đó là constructor. 

2. Abstract Factory Design pattern 

Đây là phần mở rộng của mẫu thiết kế trước đó. Nó bổ sung thêm một lớp abstract (trừu tượng) khác trên mẫu thiết kế Factory. Trong trường hợp này, bản thân Factory là abtract (trừu tượng), cho phép các chương trình chọn cách triển khai Factory khác nhau, tạo ra đặc tính khác nhau của cùng một sản phẩm tùy thuộc vào localization và các yêu cầu khác. 

3. Builder Design Pattern

Builder là một mẫu thiết kế sáng tạo cho phép bạn xây dựng các object phức tạp theo từng bước. Mẫu này cho phép bạn tạo ra các kiểu và cách biểu diễn khác nhau của một object bằng cách sử dụng cùng một construction code.

4. Singleton Design Pattern

Singleton là một mẫu thiết kế sáng tạo cho phép bạn đảm bảo rằng một class chỉ có một instance, đồng thời cung cấp một điểm truy cập toàn cầu cho phiên bản này.

Tuy nhiên, với sự ra đời của test driven programming, Singleton giờ đây đã trở thành một mô hình nhận được nhiều phản đối vì không linh hoạt trong việc cung cấp các phương pháp test double trong quá trình unit test. Singleton giống như các phương thức tĩnh, rất khó bắt chước,  trong khi đó test driven development lại cần điều ngược lại.

5. Prototype Design Pattern 

Prototype Pattern cung cấp cơ chế để copy từ object ban đầu sang object mới và thay đổi giá trị một số thuộc tính nếu cần.

II. Nhóm Structural 

Structural design patterns (Mẫu thiết kế cấu trúc) trong Java là một tập hợp các mẫu thiết kế tập trung vào việc tổ chức và kết hợp các class và object để tạo thành các cấu trúc lớn hơn. Các mẫu này nhằm mục đích nâng cao tính linh hoạt, khả năng sử dụng lại và khả năng bảo trì của code bằng cách thúc đẩy sự cộng tác giữa class và object. Dưới đây là chi tiết các mẫu trong nhóm structural:

6. Decorator Design Pattern

Đây là một mẫu thiết kế cấu trúc cho phép bạn đính kèm các hành vi mới vào các object, bằng cách đặt các object này bên trong các object khác, được bao bọc đặc biệt có chứa các hành vi đó.

7. Adapter Design Pattern

Mẫu này được sử dụng để chuyển đổi giao diện, giúp hai bên có thể làm việc cùng nhau thông qua giao diện trung gian, không cần thay đổi code của lớp có sẵn cũng như class đang viết.

8. Composite Design Pattern

Mẫu Composite cho phép khách hàng xử lý các collection object và các object riêng lẻ một cách thống nhất. Một cách để xác định mẫu Composite là cấu trúc dạng cây.

Ví dụ: trong cây Tổ chức, một số nhân viên là “Cấp quản lý” và có một nhóm nhân viên báo cáo cho họ gọi là “Nhân viên bình thường”. Nếu chúng ta có một phương thức gọi là directs() trả về nhân viên dưới quyền “Cấp quản lý”, thì “Nhân viên bình thường” có thể trả về danh sách trống, trong khi Nhân viên là “Cấp quản lý” sẽ trả về danh sách “Nhân viên”.

9. Facade Design Pattern

Công việc duy nhất của mẫu thiết kế Facade là làm cho giao diện sử dụng đơn giản hơn. Nó được sử dụng để đơn giản hóa giao diện của một hoặc nhiều class để dễ sử dụng hơn.

10. Proxy Design Pattern

Proxy là một mẫu thiết kế cấu trúc cho phép bạn kiểm soát quyền truy cập của một đối tượng vì nhiều lý do khác nhau, ví dụ như Bảo mật, Hiệu suất, Bộ đệm, v.v.. Proxy giúp kiểm soát quyền truy cập vào đối tượng ban đầu, cho phép bạn thực hiện điều gì đó trước hoặc sau khi yêu cầu được chuyển đến đối tượng đó.

11. Flyweight Design Pattern

Flyweight là một mẫu thiết kế cấu trúc cho phép bạn đưa nhiều object hơn vào lượng RAM có sẵn, bằng cách chia sẻ các phần trạng thái chung giữa nhiều object thay vì giữ tất cả dữ liệu trong từng object.

Bằng cách giảm chi phí bộ nhớ, Flyweight giúp nâng cao hiệu suất, đặc biệt là trong các ứng dụng sử dụng nhiều tài nguyên và cho phép tạo một số lượng lớn object mà không tiêu tốn quá nhiều bộ nhớ.
Mẫu Flyweight cũng được sử dụng rộng rãi trong JDK, ví dụ như các phương thức Integer.valueOf() hoặc String.valueOf().

12. Bridge Design Pattern

Bridge là một mẫu thiết kế cấu trúc cho phép bạn chia một class lớn hoặc một tập hợp các class có liên quan chặt chẽ thành hai hệ thống phân cấp riêng biệt là trừu tượng hóa (abstraction) và  tính hiện thực (implementation).

Nó tạo điều kiện cho việc cấu trúc code tốt hơn, tăng cường khả năng sử dụng lại code và đơn giản hóa việc bảo trì các hệ thống phức tạp bằng cách cung cấp sự tách biệt rõ ràng giữa sự trừu tượng hóa và việc triển khai chúng.

III. Nhóm Behavioral

Nhóm Behavioral (nhóm hành vi) là một tập hợp các mẫu thiết kế tập trung vào việc xác định giao tiếp và tương tác giữa các object và class. Các mẫu này thúc đẩy tính linh hoạt, khả năng sử dụng lại và khả năng bảo trì bằng cách gói gọn các hành vi khác nhau trong các object riêng biệt.

Các mẫu này giúp nâng cao khả năng tổ chức và cộng tác tổng thể của các ứng dụng Java, làm cho chúng có khả năng mở rộng và thích ứng tốt hơn với các thay đổi.

Sau đây là một số mẫu thiết kế rất hữu ích cho các lập trình viên Java.

13. Strategy Design Pattern 

Strategy là một mẫu thiết kế hành vi cho phép bạn xác định một nhóm thuật toán, đặt mỗi thuật toán vào một class riêng biệt và làm cho các object của chúng có thể hoán đổi cho nhau.

Mẫu này dựa trên nguyên tắc Open Closed design nhằm thúc đẩy cách viết code có thể mở rộng mà không cần chạm vào code đã được thử và kiểm tra.

14. State Design Pattern

 State Pattern là một mẫu thiết kế hành vi cho phép một object thay đổi hành vi của nó khi trạng thái bên trong của nó thay đổi. 

15. Command Design Pattern

Command là một mẫu thiết kế hành vi biến request thành một object độc lập chứa tất cả thông tin về request. Việc chuyển đổi này cho phép bạn chuyển các request dưới dạng phương thức arguments, delay hoặc queue để thực thi request và hỗ trợ các hoạt động không thể hoàn tác.

Người request chỉ biết về Command object và không biết chi tiết cụ thể về object thực tế, điều này làm giảm sự kết hợp giữa người request và đối tượng hành động.

Tất cả những gì người request cần biết là phương thức gọi trên command object, sau đó ủy quyền request cho đối tượng hành động cụ thể. 

16. Template Design Pattern

Đây là một mẫu thiết kế hành vi xác định framework của thuật toán trong lớp cha (Superclasses) nhưng cho phép các lớp con (sub class) ghi đè các bước cụ thể của thuật toán mà không thay đổi cấu trúc của nó.

17. Observer Design Pattern

Observer là một mẫu thiết kế hành vi cho phép bạn xác định cơ chế đăng ký để thông báo cho nhiều object về bất kỳ sự kiện nào xảy ra với object mà chúng đang quan sát.

18. Iterator design Pattern

Iterator là một mẫu thiết kế hành vi cho phép bạn duyệt qua các phần tử của một collection mà không cần phải hiểu rõ về những chi tiết bên trong của những tập hợp này. (list, stack, tree, v.v.).

Mẫu này giúp thúc đẩy khả năng sử dụng lại code, đơn giản hóa việc truyền tải collection và tăng cường khả năng bảo trì bằng cách tách biệt các vấn đề lặp lại khỏi chức năng cốt lõi.

19. Visitor Design Pattern

Visitor là một mẫu thiết kế hành vi cho phép bạn tách biệt các thuật toán khỏi các object mà chúng hoạt động trên đó.

20. Chain of Responsibility Pattern

Đây là một mẫu thiết kế hành vi cho phép bạn chuyển các request dọc theo một chuỗi handler. Khi nhận được request, mỗi handler sẽ quyết định xử lý yêu cầu hoặc chuyển nó cho handler tiếp theo trong chuỗi.

21. Interpreter Design Pattern

Đây là một mẫu hành vi giúp ích cho việc tạo trình thông dịch ngôn ngữ. Nó cho phép diễn giải một ngôn ngữ hoặc biểu thức nhất định bằng cách xác định ngữ pháp của nó và cung cấp trình thông dịch để đánh giá và thực hiện các biểu thức.

Interpreter thúc đẩy khả năng mở rộng và bảo trì bằng cách tách language-specific logic khỏi phần còn lại của ứng dụng, giúp việc giới thiệu các tính năng hoặc biến thể ngôn ngữ mới dễ dàng hơn.

Interpreter Design Pattern

22. Mediator Design Pattern

Mediator là một mẫu hành vi tạo điều kiện thuận lợi cho việc giao tiếp giữa nhiều object mà không cần dependency trực tiếp. Nó thúc đẩy sự ghép nối lỏng lẻo (loose coupling) bằng cách mang đến một bộ mediator hoạt động như một trung tâm liên lạc.

23. Memento Design Pattern

Memento là một mẫu thiết kế cho phép bạn lưu và khôi phục trạng thái trước đó của một object mà không tiết lộ chi tiết về việc triển khai nó. Mẫy này giúp ích trong việc đóng gói dữ liệu và duy trì tính toàn vẹn của object, vì trạng thái vẫn bị ẩn khỏi truy cập từ bên ngoài.

Đây là sơ đồ thể hiện mối tương quan giữa các mẫu thiết kế:

 relationship between different object oriented design patterns

VietnamWorks inTECH