post's image

Design pattern tổng hợp tiếng việt

Ghost wrote 13 days ago (May 31, 2025) with 42👁️ | 12 mins read

Số là xài cũng nhiều nhưng chả có tổng hợp nên mỗi lần nhắc là lại quên

Design Patterns: Hướng Dẫn Nhanh và Ứng Dụng

Design patterns là các giải pháp đã được chứng minh cho các vấn đề thường gặp trong thiết kế phần mềm. Chúng không phải là các đoạn code cụ thể mà là các khuôn mẫu hoặc bản thiết kế mà bạn có thể áp dụng trong các tình huống khác nhau. Việc hiểu và sử dụng design patterns giúp code của bạn dễ bảo trì, tái sử dụng và mở rộng hơn. Thậm chí có nhiều người chưa học design pattern nhưng gặp vấn đề cũng đã tái phát minh các design giống với việc tái phát minh bánh xe.

Bài viết này sẽ điểm qua các nhóm design patterns chính và một số mẫu quan trọng trong mỗi nhóm.

1. Nhóm Creational Patterns (Mẫu Khởi Tạo)

Nhóm này tập trung vào việc làm thế nào các đối tượng được tạo ra.

  • Singleton:

    • Mục đích: Đảm bảo chỉ có một instance duy nhất của một lớp.
    • Ứng dụng:
      • Quản lý kết nối Database: Đảm bảo chỉ có một kết nối duy nhất đến database để tránh lãng phí tài nguyên và quản lý transaction tập trung hơn. Ví dụ, trong một ứng dụng, bạn chỉ muốn có một instance của lớp quản lý kết nối đến MySQL.
      • Quản lý cấu hình: Chỉ cần đọc cấu hình từ file một lần và chia sẻ instance cấu hình đó cho toàn bộ ứng dụng.
      • Logging: Một logger instance duy nhất để ghi log tập trung vào một file hoặc hệ thống.
  • Factory Method:

    • Mục đích: Cho phép lớp con quyết định loại đối tượng sẽ được tạo.
    • Ứng dụng:
      • Tạo các loại sản phẩm khác nhau: Một nhà máy sản xuất có thể tạo ra nhiều loại xe (ô tô, xe máy, xe đạp) dựa trên yêu cầu. Factory Method cho phép lớp nhà máy quyết định loại xe nào sẽ được tạo mà không cần biết trước lớp cụ thể.
      • Kết nối đến các hệ thống khác nhau: Ứng dụng có thể cần kết nối đến nhiều loại database khác nhau (MySQL, PostgreSQL, SQL Server). Factory Method có thể được sử dụng để tạo ra các đối tượng kết nối database tương ứng.
  • Abstract Factory:

    • Mục đích: Tạo ra các họ đối tượng liên quan mà không cần chỉ định lớp cụ thể.
    • Ứng dụng:
      • Giao diện người dùng đa nền tảng: Tạo ra các bộ giao diện người dùng (buttons, text fields, etc.) khác nhau cho các hệ điều hành khác nhau (Windows, macOS) nhưng vẫn đảm bảo tính nhất quán về giao diện của từng nền tảng.
      • Làm việc với các API dịch vụ web khác nhau: Khi ứng dụng cần tương tác với nhiều dịch vụ web có API khác nhau nhưng có các nhóm chức năng tương tự.
  • Builder:

    • Mục đích: Xây dựng các đối tượng phức tạp theo từng bước.
    • Ứng dụng:
      • Tạo đối tượng Email: Một đối tượng email có thể có nhiều phần (to, from, subject, body, attachments). Builder giúp tạo đối tượng email một cách rõ ràng và dễ đọc, cho phép thiết lập các phần một cách tùy chọn.
      • Xây dựng câu truy vấn SQL: Tạo các câu truy vấn SQL phức tạp với nhiều điều kiện, sắp xếp, giới hạn một cách dễ dàng.
  • Prototype:

    • Mục đích: Tạo đối tượng mới bằng cách sao chép một đối tượng mẫu.
    • Ứng dụng:
      • Tạo bản sao của các đối tượng phức tạp: Khi việc tạo mới một đối tượng tốn nhiều tài nguyên (ví dụ: đối tượng chứa nhiều dữ liệu đã được tính toán), việc sao chép một prototype có thể nhanh hơn.
      • Undo/Redo: Lưu trữ trạng thái của đối tượng dưới dạng prototype để có thể khôi phục lại sau này.

2. Nhóm Structural Patterns (Mẫu Cấu Trúc)

Nhóm này tập trung vào cách các lớp và đối tượng được tổ chức để tạo thành các cấu trúc lớn hơn.

  • Adapter:

    • Mục đích: Giúp các interface không tương thích làm việc cùng nhau.
    • Ứng dụng:
      • Sử dụng thư viện bên thứ ba: Khi bạn muốn sử dụng một thư viện mà interface của nó không khớp với interface mà ứng dụng bạn đang mong đợi. Ví dụ, bạn có một interface PaymentGateway nhưng muốn sử dụng một thư viện thanh toán chỉ có interface ExternalPaymentService. Adapter sẽ giúp cầu nối hai interface này.
  • Bridge:

    • Mục đích: Tách abstraction và implementation để chúng có thể thay đổi độc lập.
    • Ứng dụng:
      • Hỗ trợ nhiều loại database với nhiều loại driver: Bạn có một abstraction cho việc truy cập database (ví dụ: DatabaseConnector) và nhiều implementation khác nhau cho các loại database cụ thể (MySQL, PostgreSQL) và các driver tương ứng. Bridge pattern giúp bạn kết hợp chúng một cách linh hoạt.
  • Composite:

    • Mục đích: Đại diện cho cấu trúc phân cấp cây.
    • Ứng dụng:
      • Xây dựng hệ thống file: File và thư mục có thể được xem như là các thành phần (components) trong một cấu trúc cây. Composite cho phép bạn thực hiện các thao tác (ví dụ: tính kích thước) trên cả file và thư mục một cách thống nhất.
      • Giao diện người dùng: Các thành phần UI (ví dụ: Panel, Button, Label) có thể được tổ chức theo cấu trúc cây.
  • Decorator:

    • Mục đích: Thêm chức năng vào đối tượng một cách động.
    • Ứng dụng:
      • Thêm các chức năng logging, caching vào một service: Bạn có một service cơ bản và muốn thêm các chức năng bổ sung mà không muốn thay đổi trực tiếp code của service đó.
  • Facade:

    • Mục đích: Cung cấp một interface đơn giản cho một hệ thống phức tạp.
    • Ứng dụng:
      • Đơn giản hóa việc sử dụng một hệ thống con phức tạp: Một hệ thống đặt hàng có thể bao gồm nhiều module (quản lý sản phẩm, giỏ hàng, thanh toán, vận chuyển). Facade cung cấp một interface đơn giản để client có thể thực hiện quy trình đặt hàng mà không cần tương tác trực tiếp với từng module.
  • Proxy:

    • Mục đích: Kiểm soát việc truy cập vào một đối tượng khác.
    • Ứng dụng:
      • Lazy loading: Tải dữ liệu của một đối tượng chỉ khi nó thực sự cần thiết.
      • Kiểm soát quyền truy cập: Chỉ cho phép một số người dùng nhất định truy cập vào một số chức năng.
      • Caching: Lưu trữ kết quả của một thao tác tốn kém để sử dụng lại sau này.

3. Nhóm Behavioral Patterns (Mẫu Hành Vi)

Nhóm này tập trung vào cách các đối tượng tương tác và phân công trách nhiệm.

  • Chain of Responsibility:

    • Mục đích: Chuyển yêu cầu qua một chuỗi các handler cho đến khi một handler xử lý nó.
    • Ứng dụng:
      • Xử lý request trong một hệ thống middleware: Mỗi middleware có thể kiểm tra và xử lý một phần của request trước khi chuyển nó cho middleware tiếp theo.
      • Xử lý ngoại lệ: Các handler ngoại lệ khác nhau có thể được định nghĩa để xử lý các loại ngoại lệ khác nhau.
  • Command:

    • Mục đích: Đóng gói một hành động thành một đối tượng.
    • Ứng dụng:
      • Undo/Redo: Lưu trữ các hành động đã thực hiện dưới dạng các đối tượng command để có thể hoàn tác hoặc thực hiện lại.
      • Menu và Toolbar: Mỗi item trong menu hoặc toolbar có thể được liên kết với một command object.
  • Observer:

    • Mục đích: Cho phép một đối tượng thông báo cho nhiều đối tượng khác khi trạng thái của nó thay đổi.
    • Ứng dụng:
      • Hệ thống thông báo: Khi có một sự kiện xảy ra (ví dụ: người dùng đăng ký mới), các thành phần khác (ví dụ: gửi email chào mừng, cập nhật thống kê) sẽ được thông báo.
  • Strategy:

    • Mục đích: Định nghĩa một họ các thuật toán và làm cho chúng có thể thay thế cho nhau.
    • Ứng dụng:
      • Tính toán chiết khấu: Có nhiều cách tính chiết khấu khác nhau (theo phần trăm, theo số tiền cố định, theo đối tượng khách hàng). Strategy pattern cho phép bạn dễ dàng thay đổi thuật toán chiết khấu.
      • Sắp xếp dữ liệu: Hỗ trợ nhiều thuật toán sắp xếp khác nhau (bubble sort, quicksort, mergesort) và cho phép người dùng chọn thuật toán phù hợp.
  • Template Method:

    • Mục đích: Định nghĩa bộ khung của một thuật toán, cho phép lớp con ghi đè các bước cụ thể.
    • Ứng dụng:
      • Xây dựng các báo cáo khác nhau: Quy trình tạo báo cáo có thể có các bước chung (ví dụ: kết nối database, lấy dữ liệu) và các bước cụ thể (ví dụ: định dạng dữ liệu cho từng loại báo cáo).
  • State:

    • Mục đích: Cho phép đối tượng thay đổi hành vi dựa trên trạng thái bên trong.
    • Ứng dụng:
      • Quản lý trạng thái của một đơn hàng: Một đơn hàng có thể có các trạng thái khác nhau (mới, đang xử lý, đã giao, đã hủy). Hành vi của đơn hàng (ví dụ: có được phép hủy hay không) sẽ thay đổi tùy thuộc vào trạng thái của nó.
  • Iterator:

    • Mục đích: Cung cấp một cách để duyệt qua các phần tử của một tập hợp mà không cần biết cấu trúc bên trong.
    • Ứng dụng:
      • Duyệt qua các phần tử của một danh sách, mảng, hoặc các cấu trúc dữ liệu phức tạp khác. Hầu hết các ngôn ngữ lập trình đều cung cấp sẵn iterator cho các collection.

Kết Luận

Đây chỉ là một cái nhìn tổng quan về các design patterns phổ biến. Việc nắm vững chúng sẽ giúp bạn trở thành một lập trình viên giỏi hơn, viết code sạch hơn và giải quyết các vấn đề thiết kế phức tạp một cách hiệu quả hơn. Hãy tìm hiểu sâu hơn về từng pattern khi bạn gặp các tình huống thực tế cần đến chúng.