[Design Pattern] Một ví dụ ứng dụng Strategy Pattern trong thực tế

0

Xin chào cả nhà! Đầu tuần mới đầy hứng khởi bằng một bài viết về design pattern nhé.

Nằm trong nhóm Behavioral Pattern, Strategy Pattern (hay còn gọi là policy pattern) là một mẫu thiết kế cho phép chọn loại thuật toán trong thời gian chạy ứng dụng.

Điều này có nghĩa là, bạn có thể định nghĩa trước một loạt các thuật toán. Sau đó, tùy vào ngữ cảnh mà có thể hoán đổi, lựa chọn thuật toán cho phù hợp.

Nghe qua tác dụng của loại pattern này, bạn có nghĩ tới việc áp dụng nó trong các con game không? Kiểu như trong game thì có nhiều mức độ khó dễ khác nhau: Mức độ dễ, trung bình và rất khó để thử thách người chơi.

Khi nào sử dụng?

Ở trên, mình có gợi ý một trường hợp có thể áp dụng mẫu thiết kế này trong lập trình. Ngoài ra, pattern này còn nhiều trường hợp thực tế có thể sử dụng nữa 😊

Để khái quát nhất có thể, mình đề xuất một vài trường hợp có thể sử dụng Strategy Pattern:

  • Trường hợp đầu tiên bạn nghĩ tới design pattern này là khi bạn cần hoán đổi nhiều thuật toán trong quá trình chạy ứng dụng.
  • Khi có nhiều câu lệnh điều kiện xung quanh một số thuật toán được định nghĩa trước
  • Khi trong một class mà có nhiều hành vi liên quan tới nhau.
  • Vân vân và mây mây,v.v…

Các sử dụng Strategy Pattern

Để dễ hình dung hơn, chúng ta có một ví dụ về một game mà có nhiều chế độ chơi khác nhau. Có phải bình thường bạn sẽ viết câu điều kiện thế này không?

//Ví dụ viết câu điều kiện không sử dụng strategy pattern
gameDifficulty(difficulty) {
  switch(difficulty){
    case 'easy':
      easyGameMode();
      break;
    case 'difficult'
      difficultMode();
      break;
  }
}

Tất nhiên, với cách viết trên hoàn toàn không sai. Và bản thân mình cũng hay viết như này.

Tuy nhiên, nếu ứng dụng ngày càng phát triển lên (điều mà ai cũng mong muốn), bạn sẽ cần bổ sung nhiều tính năng hơn, nhiều chế độ chơi hơn… Đến lúc đó, bạn sẽ gặp vấn đề về clean code (cụ thể là nguyên tắc SOLID principle of Open Closed). Tức là câu lệnh điều kiện quá dài (các câu lệnh điều kiện if…else hoặc switch…case)

(Mình cũng đã từng có bài viết về vấn đề câu lệnh điều kiện quá dài và một cách giải quyết tại đây: [Clean code- JS] Đừng viết switch case như này nữa!)

Cách giải quyết hôm nay mình đề xuất nó tổng quát hơn so với bài viết trước.

// Định nghĩa một class tương ứng với từng chế độ chơi
const strategies = {
  easy: easyGameMode(),
  difficult: difficultGameMode(),
  // Các chế độ chơi game khác. Có thể thêm sau này...
  __default__: normalGameMode()
}

const easyGameMode = (game) => {
  game.level(1);
  // Thuật toán tương ứng với chế độ chơi easy
  return game;
}

const normalGameMode= (game) => {
  game.level(2);
  // Thuật toán tương ứng với chế độ chơi normal
  return game;
}

const difficultGameMode = (game) => {
  game.level(3);
  // Thuật toán tương ứng với chế độ chơi difficult
  return game;
}

const startGame = (game, level) => {
  const gameModifier = strategies[level] ?? strategies.__default__;
  return gameModifier(game, level);
}

Ưu điểm của Strategy Pattern 🏆

  • Chúng ta không sử dụng các câu lệnh điều kiện if…else hay switch…case. Vì các câu lệnh điều kiện rất khó thực hiện unit test. Chưa kể, càng mở rộng ứng dụng, câu điều kiện càng dài và phức tạp hơn.
  • Dễ dàng mở rộng thêm tính năng cho ứng dụng.
  • Dễ đọc code hơn. Lý do là vì bạn đã tách ra các hàm riêng biệt và có tên hàm. Do đó, bạn đọc tên hàm là đủ biết hàm đó làm gì rồi.

Trên đây là một vài ý kiến cá nhân về mẫu thiết kế Strategy Pattern. Tất nhiên, design pattern không chỉ ứng dụng cho một ngôn ngữ lập trình nào cả, bạn có thể dùng ở bất cứ dự án nào, bất cứ ngôn ngữ nào…

Mình hi vọng qua bài viết này, bạn có thể áp dụng cách viết code được clean hơn, hạn chế những “câu từ khó nghe” từ các anh Leader 😊

💦 Đọc thêm về design pattern:

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng

Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Thông báo