# Stretagy

# 概念

定义一系列算法(策略),将他们封装起来,并且使它们可以相互替换

# 结构

一般包含三个角色:

  • 抽象策略:定义算法的接口
  • 具体策略:实现不同的算法
  • 环境类: 持有一个策略对象,并对外提供统一的调用入口

# 例子

// 抽象策略
interface PaymentStrategy {
    void pay(int amount);
}

// 具体策略 - 支付宝支付
class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用支付宝支付:" + amount + " 元");
    }
}

// 具体策略 - 微信支付
class WeChatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用微信支付:" + amount + " 元");
    }
}

// 具体策略 - 信用卡支付
class CreditCardStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用信用卡支付:" + amount + " 元");
    }
}

// 环境类
class PaymentContext {
    private PaymentStrategy strategy;

    // 允许动态切换策略
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void pay(int amount) {
        if (strategy == null) {
            throw new IllegalStateException("未设置支付策略");
        }
        strategy.pay(amount);
    }
}

// 客户端
public class StrategyPatternDemo {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();

        // 使用支付宝
        context.setPaymentStrategy(new AlipayStrategy());
        context.pay(100);

        // 切换为微信
        context.setPaymentStrategy(new WeChatPayStrategy());
        context.pay(200);

        // 切换为信用卡
        context.setPaymentStrategy(new CreditCardStrategy());
        context.pay(300);
    }
}

# 优点

  • 避免了大量的 if-else 或 switch-case。
  • 可以方便地增加新的策略,而无需修改原有代码(符合开闭原则)。
  • 策略可以灵活切换,扩展性好。

# 缺点

  • 客户端需要知道所有策略,并手动选择合适的策略。
  • 如果策略很多,类的数量会增加。

# 使用场景

  • 一个系统需要动态选择不同的算法,比如支付方式、压缩算法、排序方式。
  • 消除复杂的条件语句,避免 if-else 嵌套。
  • 多个类的行为差别只在于算法或逻辑时,可以用策略模式替代继承。

# 策略模式和简单工厂模式结合

客户端的代码可以更简洁,只传参数,又工厂类选择要创建的具体策略。

// 策略接口
interface PaymentStrategy {
    void pay(int amount);
}

// 具体策略 - 支付宝支付
class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用支付宝支付:" + amount + " 元");
    }
}

// 具体策略 - 微信支付
class WeChatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用微信支付:" + amount + " 元");
    }
}

// 具体策略 - 信用卡支付
class CreditCardStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用信用卡支付:" + amount + " 元");
    }
}

// 简单工厂 - 根据参数返回不同的策略
class PaymentStrategyFactory {
    public static PaymentStrategy getStrategy(String type) {
        if ("alipay".equalsIgnoreCase(type)) {
            return new AlipayStrategy();
        } else if ("wechat".equalsIgnoreCase(type)) {
            return new WeChatPayStrategy();
        } else if ("creditcard".equalsIgnoreCase(type)) {
            return new CreditCardStrategy();
        }
        throw new IllegalArgumentException("未知的支付方式: " + type);
    }
}

// 环境类
class PaymentContext {
    private PaymentStrategy strategy;

    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void pay(int amount) {
        strategy.pay(amount);
    }
}

// 客户端
public class StrategyFactoryDemo {
    public static void main(String[] args) {
        // 客户端只需告诉工厂支付方式
        PaymentStrategy strategy1 = PaymentStrategyFactory.getStrategy("alipay");
        PaymentContext context1 = new PaymentContext(strategy1);
        context1.pay(100);

        PaymentStrategy strategy2 = PaymentStrategyFactory.getStrategy("wechat");
        PaymentContext context2 = new PaymentContext(strategy2);
        context2.pay(200);

        PaymentStrategy strategy3 = PaymentStrategyFactory.getStrategy("creditcard");
        PaymentContext context3 = new PaymentContext(strategy3);
        context3.pay(300);
    }
}

工厂类的代码可以写在context类的构造函数中,使用switch语句根据传入的参数选择创建对应的策略。

// 策略接口
interface PaymentStrategy {
    void pay(int amount);
}

// 具体策略 - 支付宝支付
class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用支付宝支付:" + amount + " 元");
    }
}

// 具体策略 - 微信支付
class WeChatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用微信支付:" + amount + " 元");
    }
}

// 具体策略 - 信用卡支付
class CreditCardStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("使用信用卡支付:" + amount + " 元");
    }
}

// 环境类
class PaymentContext {
    PaymentStrategy strategy;

    public PaymentContext(String type) {
        switch (type) {
            case "Alipay":
                strategy = new AlipayStrategy();
                break;
            case "WeChat":
                strategy = new WeChatPayStrategy();
                break;
            case "CreditCard":
                strategy = new CreditCardStrategy();
                break;
        }
    }

    public void pay(int amount) {
        strategy.pay(amount);
    }
}

// 客户端
public class StrategyFactoryDemo {
    public static void main(String[] args) {
        // 客户端只需告诉工厂支付方式
        PaymentContext context1 = new PaymentContext("Alipay");
        context1.pay(100);

        PaymentContext context2 = new PaymentContext("WeChat");
        context2.pay(200);

        PaymentContext context3 = new PaymentContext("CreditCard");
        context3.pay(300);
    }
}

# 注意

  • 策略模式通过定义一系列算法(在这里是运输方式),封装每一个算法,并使它们可以相互替换,特别适合于有多种类似行为或策略的系统。