VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
Kiến trúc và chất lượng codeDesign pattern
Bài 11/17
5 phút

Strategy

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ũ. Discount ở bài OCP và Shipping ở bài Composition đều là Strategy.

Ví dụ

// Main.java
void main() {
    var checkout = new Checkout(new StandardShipping());
    long total = checkout.total(200000);
    System.out.println(total);   // 220000
}

// ShippingStrategy.java
interface ShippingStrategy {
    long fee(long orderTotal);
}

// StandardShipping.java
class StandardShipping implements ShippingStrategy {
    @Override
    public long fee(long orderTotal) {
        if (orderTotal >= 500000) {
            return 0;
        }
        return 20000;
    }
}

// ExpressShipping.java
class ExpressShipping implements ShippingStrategy {
    @Override
    public long fee(long orderTotal) {
        return 50000;
    }
}

// Checkout.java
class Checkout {
    private final ShippingStrategy shipping;

    public Checkout(ShippingStrategy shipping) {
        this.shipping = shipping;
    }

    public long total(long subtotal) {
        return subtotal + shipping.fee(subtotal);
    }
}
  • ShippingStrategy đạ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>> ShippingStrategy fee(orderTotal) StandardShipping ExpressShipping Checkout
Checkout chỉ biết interface, mỗi cách giao là một class

Thử ngay

Giữ các file của ví dụ. Thêm cách "khách tự đến lấy", miễn phí, rồi thay main trong Main.java để dùng thử:

// Main.java
void main() {
    System.out.println(new Checkout(
        new ExpressShipping()).total(200000));
    System.out.println(new Checkout(
        new PickupShipping()).total(200000));
}

// PickupShipping.java
class PickupShipping implements ShippingStrategy {
    @Override
    public long fee(long 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
long fee(String method, long orderTotal) {
    if (method.equals("express")) {
        return 50000;
    }
    if (orderTotal >= 500000) {
        return 0;
    }
    return 20000;
}
// ĐÚNG — nơi gọi chỉ nhận interface
// Checkout.java
class Checkout {
    private final ShippingStrategy shipping;

    public Checkout(ShippingStrategy shipping) {
        this.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.

Tự kiểm tra

0/3 câu
Câu 1

Cửa hàng thêm cách giao "giao trong 2 giờ". Với Strategy, cần làm gì?

Câu 2

Checkout biết gì về cách tính phí giao hàng?

Câu 3

Nguyên lý SOLID nào đứng sau Strategy rõ nhất?

Refactor an toànFactory

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