Menu
CoddyTech

策略模式

本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 55 课,共 70 课。

策略模式是一种行为型模式,它让你可以定义一组算法,将每种算法封装在自己的类中,并在运行时互换使用。你无需将行为硬编码,而是将所需的策略注入对象。

这个模式由三部分组成:定义算法契约的策略接口、实现不同行为的具体策略类,以及使用策略的上下文类:

public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via Credit Card");
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via PayPal");
}

public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentMethod(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy;
    }
    
    public void Checkout(decimal total)
    {
        _paymentStrategy.Pay(total);
    }
}

上下文(ShoppingCart)不知道自己使用的是哪种支付方式,它只会对传入的策略调用 Pay():

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // 通过信用卡支付了 99.99

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // 通过 PayPal 支付了 49.99

策略模式可以消除复杂的条件逻辑。添加新的支付方式,只需创建一个实现 IPaymentStrategy 的新类,无需修改 ShoppingCart。这样,你的代码就可以扩展,但无需修改。

challenge icon

挑战

简单

我们来使用策略模式构建一个运费计算器。不同的配送方式有不同的定价算法,你的系统应该能够在运行时切换算法,而不改变核心订单处理逻辑。

你需要将代码组织到三个文件中:

  • ShippingStrategy.cs:在 Shipping 命名空间中定义一个 IShippingStrategy 接口,其中包含一个方法 CalculateCost(double weight),该方法返回一个 double。然后创建三个具体的策略类:
    • StandardShipping:按 weight * 1.5 计算费用
    • ExpressShipping:按 weight * 3.0 + 5.0 计算费用(包含固定的快递费用)
    • OvernightShipping:按 weight * 5.0 + 10.0 计算费用(高级服务,基础费用更高)
  • OrderProcessor.cs:在同一命名空间中创建一个 OrderProcessor 类。它是使用配送策略的上下文类,其中应包含:
    • 一个用于保存当前 IShippingStrategy 的私有字段
    • 一个用于更改配送策略的 SetShippingMethod(IShippingStrategy strategy) 方法
    • 一个 ProcessOrder(double weight) 方法,该方法使用当前策略计算并返回运费
  • Program.cs:创建一个 OrderProcessor,并演示如何在运行时切换配送策略,从而将所有内容整合起来。同一个处理器只需更改策略,就能使用不同的算法计算费用。

你将收到两个输入:

  • 配送方式类型:standard、express 或 overnight
  • 包裹重量,以小数表示(例如,4.5)

创建一个 OrderProcessor,根据输入类型设置相应的配送策略,然后处理订单并打印计算出的费用。

例如,如果输入是 express 和 4.5,输出应为:

18.5

这展示了策略模式的强大之处:你的 OrderProcessor 本身不包含任何运费计算逻辑。它只会将计算委托给指定的策略,因此你可以轻松添加新的配送方式(例如 DroneDelivery),而完全不必修改处理器!

亲手试试

using System;
using Shipping;

class Program
{
    public static void Main(string[] args)
    {
        // 读取输入
        string shippingType = Console.ReadLine();
        double weight = Convert.ToDouble(Console.ReadLine());

        // TODO: 创建一个 OrderProcessor 实例

        // TODO: 根据 shippingType("standard"、"express" 或 "overnight"),
        // 创建对应的配送策略,并将其设置到处理器上

        // TODO: 处理订单并打印计算出的费用
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C# 在线编译器