策略模式
基础概念
什么是策略模式?
答案: 策略模式(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");练习题
- 策略模式和工厂模式的区别?
- 如何避免策略类爆炸?
- 策略模式如何消除if-else?
- 策略模式的应用场景有哪些?
- 如何实现策略的动态加载?