Menu
CoddyTech

Mẫu Strategy

Thuộc phần Lập trình hướng đối tượng trong hành trình Dart của Coddy. Bài học 93 trên 110.

Mẫu Strategy pattern cho phép bạn định nghĩa một nhóm thuật toán, đóng gói từng thuật toán trong lớp riêng và thay thế chúng cho nhau khi chương trình chạy. Thay vì viết cứng hành vi trong một lớp, bạn truyền hành vi qua một giao diện, nhờ đó có thể thay đổi các chiến lược mà không cần sửa lớp sử dụng chúng.

Hãy xét một hệ thống thanh toán cần hỗ trợ nhiều phương thức thanh toán khác nhau. Thay vì dùng các câu lệnh điều kiện để xử lý từng phương thức, bạn định nghĩa một giao diện chiến lược và tạo các phần triển khai cụ thể:

abstract class PaymentStrategy {
  void pay(double amount);
}

class CreditCardPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$$amount with Credit Card');
}

class PayPalPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$$amount with PayPal');
}

class ShoppingCart {
  PaymentStrategy _paymentStrategy;

  ShoppingCart(this._paymentStrategy);

  void setPaymentStrategy(PaymentStrategy strategy) {
    _paymentStrategy = strategy;
  }

  void checkout(double total) {
    _paymentStrategy.pay(total);
  }
}

void main() {
  var cart = ShoppingCart(CreditCardPayment());
  cart.checkout(99.99);  // Đã thanh toán $99.99 bằng thẻ tín dụng

  cart.setPaymentStrategy(PayPalPayment());
  cart.checkout(49.99);  // Đã thanh toán $49.99 bằng PayPal
}

ShoppingCart không biết cũng không quan tâm cách thanh toán hoạt động, nó chỉ giao việc đó cho chiến lược hiện đang được thiết lập. Bạn có thể thêm phương thức thanh toán mới bằng cách tạo các lớp chiến lược mới mà không cần chỉnh sửa code của giỏ hàng. Mẫu này rất phù hợp khi bạn có nhiều cách thực hiện một hành động và muốn chọn hoặc chuyển đổi giữa chúng một cách linh hoạt.

challenge icon

Thử thách

Dễ

Hãy cùng xây dựng một hệ thống định dạng văn bản bằng mẫu Strategy nhé! Bạn sẽ tạo một hệ thống có thể áp dụng nhiều chiến lược định dạng khác nhau cho văn bản, cho phép người dùng chuyển đổi linh hoạt giữa các định dạng mà không cần thay đổi bộ xử lý văn bản cốt lõi.

Bạn sẽ sắp xếp code vào hai tệp:

  • formatting_strategies.dart: Tạo hệ thống chiến lược tại đây. Định nghĩa lớp trừu tượng FormattingStrategy với phương thức String format(String text). Sau đó, triển khai ba chiến lược cụ thể:
    • UppercaseStrategy - chuyển toàn bộ văn bản thành chữ hoa
    • LowercaseStrategy - chuyển toàn bộ văn bản thành chữ thường
    • TitleCaseStrategy - viết hoa chữ cái đầu tiên của mỗi từ (tách bằng dấu cách, viết hoa ký tự đầu tiên của mỗi từ, các ký tự còn lại viết thường)
    Tạo thêm lớp TextProcessor để lưu một FormattingStrategy. Lớp này cần có hàm khởi tạo nhận chiến lược ban đầu, phương thức setStrategy() để thay đổi chiến lược khi chương trình đang chạy và phương thức process(String text) để áp dụng chiến lược hiện tại rồi trả về kết quả đã định dạng.
  • main.dart: Nhập các chiến lược định dạng và minh họa cách mẫu Strategy cho phép chuyển đổi hành vi linh hoạt. Tạo một TextProcessor bắt đầu với UppercaseStrategy. Xử lý văn bản hello world rồi in kết quả ra. Sau đó, chuyển sang LowercaseStrategy, xử lý HELLO WORLD rồi in kết quả ra. Cuối cùng, chuyển sang TitleCaseStrategy, xử lý the quick brown fox rồi in kết quả ra.

Ví dụ này cho thấy sức mạnh của mẫu Strategy: TextProcessor không cần biết chi tiết cách định dạng hoạt động. Nó chỉ chuyển việc xử lý cho chiến lược hiện được thiết lập, giúp bạn dễ dàng thêm các tùy chọn định dạng mới mà không phải sửa đổi bộ xử lý!

Kết quả đầu ra mong đợi:

HELLO WORLD
hello world
The Quick Brown Fox

Tự làm thử

import 'formatting_strategies.dart';

void main() {
  // TODO: Tạo một TextProcessor, bắt đầu với UppercaseStrategy
  
  // TODO: Xử lý văn bản 'hello world' và in ra kết quả
  
  // TODO: Chuyển sang LowercaseStrategy
  
  // TODO: Xử lý 'HELLO WORLD' và in ra kết quả
  
  // TODO: Chuyển sang TitleCaseStrategy
  
  // TODO: Xử lý 'the quick brown fox' và in ra kết quả
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Dart online