Tìm hiểu về Design Patterns

Tìm hiểu về Design Patterns

Trong lĩnh vực phát triển phần mềm, bất kể bạn là ai, làm việc ở đâu, sử dụng ngôn ngữ lập trình gì hay xây dựng ứng dụng gì thì SỰ THAY ĐỔI luôn là người bạn đồng hành thân thiết như hình với bóng của bạn. Khi có một yêu cầu thay đổi phần mềm mới xuất hiện, một số lập trình viên chưa có nhiều kinh nghiệm sẽ cố gắng viết ra những đoạn code đáp ứng được sự thay đổi này một cách tạm thời mà không thực sự quan tâm đến tính tái sử dụng, tính mở rộng và tính bảo trì của đoạn code đó trong trường hợp có yêu cầu thay đổi mới xuất hiện.

Chính thói quen không hay này dẫn đến việc họ hoặc team của họ phải dành phần lớn thời gian cho giai đoạn bảo trì phần mềm sau đó. Trong trường hợp xấu nhất, nếu như thiết kế hiện tại không thể đáp ứng được bất kỳ một yêu cầu thay đổi phần mềm nào nữa đồng nghĩa với việc họ phải đập bỏ toàn bộ phần mềm hiện tại và tiến hành xây dựng lại mọi thứ từ đầu. Nghe thật không vui tí nào. Đó cũng chính là lý do mà siêu anh hùng đẹp trai khoai to mang tên Design Patterns đã xuất hiện để giải cứu thế giới =D

Tìm hiểu về Design Patterns

Design Patterns

Design Patterns là cái gì thế?

Không khó để các bạn có thể tìm được hàng tá định nghĩa về design patterns trên Internet. Theo cách hiểu của mình, design patterns đơn giản là tập hợp của những giải pháp cho những vấn đề thường gặp trong lĩnh vực thiết kế phần mềm. Thay vì cung cấp một bản thiết kế hoàn chỉnh “tận răng” để bạn có thể bê trực tiếp vào dự án của mình, chúng giống như các khuôn mẫu nhằm giúp bạn hình dung ra cách giải quyết vấn đề để có thể tự triển khai và áp dụng vào dự án phần mềm của mình.

Tìm hiểu về Design Patterns

Một ví dụ đơn giản về Strategy Pattern

Nhìn chung, mỗi design pattern đều có bốn thành phần cơ bản sau:

  • Tên: Tên của design pattern, phân biệt với các design pattern khác.
  • Vấn đề đặt ra: Vấn đề mà design pattern này được áp dụng.
  • Giải pháp: Mô tả những thành phần tạo nên thiết kế, mối liên hệ, trách nhiệm và sự phối hợp qua lại giữa các thành phần đó.
  • Đánh giá: Những hệ quả, lợi ích cũng như hạn chế khi sử dụng design pattern này.

Xài Design Patterns có lợi ích gì không nhỉ?

Câu trả lời là có nhé, hơi bị nhiều là đằng khác :v

  • Do là tập hợp của những giải pháp đã được tối ưu hóa và đã được kiểm chứng, design patterns giúp đẩy nhanh tốc độ phát triển phần mềm. Thay vì phải vò đầu bứt tóc tự tìm kiếm giải pháp cho một vấn đề đã được chứng minh, giờ đây bạn chỉ cần tìm ra design pattern có thể giải quyết được vấn đề và áp dụng nó là xong.
  • Sử dụng design pattern giúp tránh được các vấn đề tiềm ẩn có thể gây ra những lỗi lớn, dễ dàng nâng cấp, bảo trì về sau.
  • Giúp cho lập trình viên có thể dễ dàng đọc hiểu code của người khác một cách nhanh chóng. Nhờ đó mọi thành viên trong team có thể dễ dàng trao đổi với nhau để cùng xây dựng dự án mà không mất quá nhiều thời gian.

Phân loại design patterns

The Gang of Fours (GoF) – nhóm tác giả huyền thoại của cuốn sách Design Patterns – Elements of Reusable Object-Oriented Software đã thống nhất chia 23 design patterns thành 3 nhóm chính là: Creational Patterns (Nhóm khởi tạo), Structural Patterns (Nhóm cấu trúc) và Behavioral Patterns (Nhóm hành vi).

Creational Patterns (Nhóm khởi tạo)

Là một lập trình viên chân chính, chắc chắn bất cứ ai trong chúng ta cũng đều dành phần lớn thời gian để khởi tạo các lớp và đối tượng. Đó cũng chính là lý do mà các design patterns dưới đây đã ra đời nhằm giúp cho việc khởi tạo các lớp và đối tượng được hiệu quả hơn trong một số trường hợp cụ thể.

TênMục đích
Abstract FactoryCung cấp một interface cho việc tạo lập các đối tượng mà không cần phải xác định lớp cụ thể tạo ra chúng.
BuilderTách rời việc xây dựng một đối tượng phức tạp khỏi biểu diễn của nó sao cho cùng một tiến trình xây dựng có thể tạo được các biểu diễn khác nhau.
Factory MethodĐịnh nghĩa interface để sinh ra đối tượng nhưng để cho lớp con quyết định lớp nào được dùng để sinh ra đối tượng.
PrototypeQuy định loại của các đối tượng cần tạo bằng cách dùng một đối tượng mẫu, tạo mới nhờ vào sao chép đối tượng mẫu này.
SingletonĐảm bảo một class chỉ có duy nhất một thể hiện và cung cấp một điểm truy xuất toàn cục đến nó.

Structural Patterns (Nhóm cấu trúc)

Các design patterns thuộc nhóm này ra đời nhằm giải quyết các vấn đề liên quan đến việc thiết lập và định nghĩa mối quan hệ giữa các đối tượng. Chúng gồm có:

TênMục đích
AdapterChuyển giao diện của một class thành giao diện phù hợp với yêu cầu.
BridgeTách rời ngữ nghĩa của một vấn đề khỏi việc cài đặt.
CompositeTổ chức các đối tượng theo cấu trúc phân cấp dạng cây, các đối tượng trong cấu trúc được thao tác theo một cách thuần nhất như nhau.
DecoratorGán thêm trách nhiệm cho đối tượng vào lúc chạy (thêm chức năng cho class).
FacadeCung cấp một interface cấp cao, dễ dùng cho một tập hợp các interface của hệ thống con (subsystem).
FlyweightChia sẻ trạng thái chung nhằm thao tác hiệu quả tài nguyên và bộ nhớ.
ProxyCung cấp một đối tượng đại diện cho một đối tượng khác để hỗ trợ hoặc kiểm soát quá trình truy xuất đến đối tượng đó.

Behavioral Patterns (Nhóm hành vi)

Các design patterns thuộc nhóm này ra đời nhằm giải quyết các vấn đề liên quan đến việc thực hiện các hành vi của đối tượng. Chúng gồm có:

TênMục đích
Chain of ResponsibilityCho phép truyền một request thông qua một chuỗi các đối tượng.
CommandMỗi request hoặc command được đóng gói và gửi đi như một đối tượng.
InterpreterHỗ trợ việc định nghĩa biểu diễn văn phạm và bộ thông dịch cho một ngôn ngữ.
IteratorTruy xuất các phần tử của đối tượng dạng tập hợp tuần tự (list, array,…).
MediatorĐịnh nghĩa một đối tượng để điều hướng việc giao tiếp giữa một số đối tượng với nhau.
MementoChỉnh sửa và phục hồi trạng thái bên trong của đối tượng mà vẫn không vi phạm việc đóng gói dữ liệu.
ObserverĐịnh nghĩa sự phụ thuộc một-nhiều giữa các đối tượng sao cho khi một đối tượng thay đổi trạng thái thì tất cả các đối tượng phụ thuộc nó cũng thay đổi theo.
StateCho phép một đối tượng thay đổi hành vi khi trạng thái bên trong của nó thay đổi.
StrategyĐóng gói các thuật toán bằng các lớp, mỗi thuật toán có thể thay đổi độc lập đối với chương trình sử dụng thuật toán, cung cấp một họ giải thuật cho phép client chọn lựa linh động một giải thuật cụ thể khi sử dụng.
Template MethodĐịnh nghĩa phần khung của một thuật toán, tức là một thuật toán tổng quát gọi đến một số phương thức chưa được cài đặt trong lớp cơ sở; việc cài đặt các phương thức được ủy nhiệm cho các lớp kế thừa.
VisitorCho phép định nghĩa thêm phép toán mới tác động lên các phần tử của một cấu trúc đối tượng mà không cần thay đổi các lớp định nghĩa cấu trúc đó.

Kết luận

Tóm lại, design patterns đóng một vai trò vô cùng quan trọng trong quá trình phát triển phần mềm và nếu biết cách áp dụng chúng một cách hợp lý. Chắc chắn code của chúng ta sẽ trở nên dễ tái sử dụng, dễ mở rộng cũng như dễ bảo trì hơn. Tuy nhiên, để có đủ trình độ trả lời được vanh vách các câu hỏi như “Đối với dự án phần mềm này nên dùng design pattern nào?” hay “Dự án phần mềm kia dùng design pattern nào là ổn?” đòi hỏi bạn phải thật sự am hiểu về design patterns cũng như phải có kinh nghiệm làm việc thực tế nhiều năm.

Trong bài viết tiếp theo của series này, mình sẽ giới thiệu tới các bạn design pattern đầu tiên mang tên “The Factory Method Pattern”.

Gửi phản hồi