VieTopikKhoá học
  • Games
  • Cá nhân
Tải app
© 2026 VieTopikChính sách bảo mậtĐiều khoản sử dụngCài appEnglish
  • Trang chủ
  • Học
  • Luyện thi
  • Cẩm nang
  • Games
  • Cá nhân
Kiến trúc và chất lượng codeDesign pattern
Bài 11/17
5 phút

Strategy

Bình luận
Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Cửa hàng có ba cách giao: tiêu chuẩn, hoả tốc và khách tự đến lấy. Mỗi cách tính phí một kiểu. Nếu viết hết vào một method, dùng if theo tên cách giao, thì mỗi lần thêm cách giao lại phải sửa method đó. Strategy tách mỗi cách tính thành một class riêng.

Khái niệm

📘 Design pattern: lời giải có tên cho một vấn đề thiết kế hay gặp.

♟️ Strategy: mỗi cách thực hiện cùng một việc được đặt trong một class riêng, các class cùng implement một interface, và nơi gọi nhận cách làm qua interface đó.

Strategy là một cách áp dụng OCP của khoá OOP: thêm cách giao là thêm class, không sửa code cũ. IDiscount ở bài OCP và IShipping ở bài Composition đều là Strategy.

Ví dụ

var checkout = new Checkout(new StandardShipping());
Console.WriteLine(checkout.Total(200000m));   // 220000

public interface IShippingStrategy
{
    decimal Fee(decimal orderTotal);
}

public class StandardShipping : IShippingStrategy
{
    public decimal Fee(decimal orderTotal)
    {
        if (orderTotal >= 500000)
        {
            return 0;
        }
        return 20000;
    }
}

public class ExpressShipping : IShippingStrategy
{
    public decimal Fee(decimal orderTotal)
    {
        return 50000;
    }
}

public class Checkout
{
    private readonly IShippingStrategy _shipping;

    public Checkout(IShippingStrategy shipping)
    {
        _shipping = shipping;
    }

    public decimal Total(decimal subtotal)
    {
        return subtotal + _shipping.Fee(subtotal);
    }
}
  • IShippingStrategy đại diện cho việc tính phí giao hàng, mỗi class là một cách tính.
  • Checkout chỉ biết interface và nhận cách tính qua constructor, như bài DIP và dependency injection.
  • Đổi cách giao là đổi object truyền vào, Checkout không đổi dòng nào.
<<interface>> IShippingStrategy Fee(orderTotal) StandardShipping ExpressShipping Checkout
Checkout chỉ biết interface, mỗi cách giao là một class

Thử ngay

Thêm cách "khách tự đến lấy", miễn phí, rồi dùng thử:

Console.WriteLine(
    new Checkout(new ExpressShipping()).Total(200000m));
Console.WriteLine(
    new Checkout(new PickupShipping()).Total(200000m));

public class PickupShipping : IShippingStrategy
{
    public decimal Fee(decimal orderTotal)
    {
        return 0;
    }
}

Đoán trước khi chạy: hai dòng in ra bao nhiêu? Phải sửa Checkout không?

Xem kết quả
250000
200000

Hoả tốc cộng 50.000, tự lấy cộng 0. Thêm PickupShipping là thêm một class mới, Checkout và hai cách giao cũ giữ nguyên.

Lỗi hay gặp

Rải if theo tên cách giao khắp code. Thêm cách giao mới phải tìm và sửa mọi chỗ có các if này, sót một chỗ là tính sai.

// SAI — thêm cách giao mới phải sửa method này
decimal Fee(string method, decimal orderTotal)
{
    if (method == "express")
    {
        return 50000;
    }
    if (orderTotal >= 500000)
    {
        return 0;
    }
    return 20000;
}
// ĐÚNG — nơi gọi chỉ nhận interface
public class Checkout
{
    private readonly IShippingStrategy _shipping;

    public Checkout(IShippingStrategy shipping)
    {
        _shipping = shipping;
    }
}

Tóm tắt

  • Design pattern là lời giải có tên cho một vấn đề thiết kế hay gặp.
  • Strategy: mỗi cách làm một class, chung một interface.
  • Nơi gọi nhận interface qua constructor, đổi cách làm không phải sửa nó.
  • Thêm cách mới là thêm class, đúng tinh thần OCP.
Refactor an toànFactory

Bình luận

Đang tải bình luận…

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt