Skip to content

策略模式

基础概念

什么是策略模式?

答案: 策略模式(Strategy Pattern)定义一系列算法,将每个算法封装起来,并使它们可以互相替换。策略模式让算法独立于使用它的客户端而变化。

使用场景

  • 多种算法可选
  • 避免多重if-else
  • 算法需要动态切换

优点

  • 算法可以自由切换
  • 避免多重条件判断
  • 扩展性好

缺点

  • 策略类数量增加
  • 客户端必须知道所有策略

实现方式

基本实现?

答案:

java
// 策略接口
public interface PaymentStrategy {
    void pay(BigDecimal amount);
}

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

// 具体策略:微信
public class WechatStrategy implements PaymentStrategy {
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("微信支付: " + amount);
    }
}

// 具体策略:银行卡
public class BankCardStrategy implements PaymentStrategy {
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("银行卡支付: " + amount);
    }
}

// 上下文
public class PaymentContext {
    private PaymentStrategy strategy;

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

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

// 使用
PaymentContext context = new PaymentContext();
context.setStrategy(new AlipayStrategy());
context.pay(new BigDecimal("100.00"));

context.setStrategy(new WechatStrategy());
context.pay(new BigDecimal("200.00"));

实际应用

优惠计算策略

答案:

java
// 折扣策略接口
public interface DiscountStrategy {
    BigDecimal calculate(BigDecimal originalPrice);
}

// 无折扣
public class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public BigDecimal calculate(BigDecimal originalPrice) {
        return originalPrice;
    }
}

// 满减策略
public class FullReductionStrategy implements DiscountStrategy {
    private BigDecimal threshold;
    private BigDecimal reduction;

    public FullReductionStrategy(BigDecimal threshold, BigDecimal reduction) {
        this.threshold = threshold;
        this.reduction = reduction;
    }

    @Override
    public BigDecimal calculate(BigDecimal originalPrice) {
        if (originalPrice.compareTo(threshold) >= 0) {
            return originalPrice.subtract(reduction);
        }
        return originalPrice;
    }
}

// 折扣策略
public class PercentageDiscountStrategy implements DiscountStrategy {
    private BigDecimal percentage;

    public PercentageDiscountStrategy(BigDecimal percentage) {
        this.percentage = percentage;
    }

    @Override
    public BigDecimal calculate(BigDecimal originalPrice) {
        return originalPrice.multiply(percentage);
    }
}

// 使用
DiscountStrategy strategy = new FullReductionStrategy(
    new BigDecimal("100"),
    new BigDecimal("20")
);
BigDecimal finalPrice = strategy.calculate(new BigDecimal("150"));

排序策略

答案:

java
// 排序策略接口
public interface SortStrategy {
    void sort(int[] array);
}

// 冒泡排序
public class BubbleSortStrategy implements SortStrategy {
    @Override
    public void sort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }
}

// 快速排序
public class QuickSortStrategy implements SortStrategy {
    @Override
    public void sort(int[] array) {
        quickSort(array, 0, array.length - 1);
    }

    private void quickSort(int[] array, int left, int right) {
        if (left < right) {
            int pivot = partition(array, left, right);
            quickSort(array, left, pivot - 1);
            quickSort(array, pivot + 1, right);
        }
    }

    private int partition(int[] array, int left, int right) {
        int pivot = array[right];
        int i = left - 1;
        for (int j = left; j < right; j++) {
            if (array[j] < pivot) {
                i++;
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
        int temp = array[i + 1];
        array[i + 1] = array[right];
        array[right] = temp;
        return i + 1;
    }
}

// 排序器
public class Sorter {
    private SortStrategy strategy;

    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;
    }

    public void sort(int[] array) {
        strategy.sort(array);
    }
}

策略+工厂

如何结合工厂模式?

答案:

java
// 策略工厂
public class PaymentStrategyFactory {
    private static Map<String, PaymentStrategy> strategies = new HashMap<>();

    static {
        strategies.put("alipay", new AlipayStrategy());
        strategies.put("wechat", new WechatStrategy());
        strategies.put("bankcard", new BankCardStrategy());
    }

    public static PaymentStrategy getStrategy(String type) {
        PaymentStrategy strategy = strategies.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的支付方式: " + type);
        }
        return strategy;
    }
}

// 使用
PaymentStrategy strategy = PaymentStrategyFactory.getStrategy("alipay");
strategy.pay(new BigDecimal("100.00"));

Spring中的策略模式

Resource接口?

答案:

java
// Resource接口
public interface Resource {
    InputStream getInputStream() throws IOException;
}

// 不同的资源加载策略
ClassPathResource resource1 = new ClassPathResource("config.properties");
FileSystemResource resource2 = new FileSystemResource("/path/to/file");
UrlResource resource3 = new UrlResource("http://example.com/file");

练习题

  1. 策略模式和工厂模式的区别?
  2. 如何避免策略类爆炸?
  3. 策略模式如何消除if-else?
  4. 策略模式的应用场景有哪些?
  5. 如何实现策略的动态加载?

Released under the MIT License.