策略模式

策略模式

定义

  • 在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

  • 在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。

  • 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

简单demo

我们假设要实现一个支付系统,支持不同的支付方式(比如:支付宝、微信、银行卡),具体的支付逻辑交由不同的策略实现。

1. 定义策略接口:PaymentStrategy

public interface PaymentStrategy {
    String getPayType();
    void pay(double amount);
}

2. 策略实现类(支付宝、微信、银行卡)

import org.springframework.stereotype.Component;

@Component
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public String getPayType() {
        return "alipay";
    }

    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付:" + amount + " 元");
    }
}
import org.springframework.stereotype.Component;

@Component
public class BankCardStrategy implements PaymentStrategy {
    @Override
    public String getPayType() {
        return "bank";
    }

    @Override
    public void pay(double amount) {
        System.out.println("使用银行卡支付:" + amount + " 元");
    }
}
import org.springframework.stereotype.Component;

@Component
public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public String getPayType() {
        return "wechat";
    }

    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付:" + amount + " 元");
    }
}

3. 策略上下文类:PaymentStrategyFactory

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class PaymentStrategyFactory {

    private final Map<String, PaymentStrategy> strategyMap = new HashMap<>();

    @Autowired
    public PaymentStrategyFactory(List<PaymentStrategy> strategies) {
        for (PaymentStrategy strategy : strategies) {
            strategyMap.put(strategy.getPayType(), strategy);
        }
    }

    public PaymentStrategy getStrategy(String payType) {
        PaymentStrategy strategy = strategyMap.get(payType);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的支付类型: " + payType);
        }
        return strategy;
    }
}

4. 测试

import org.example.design_pattern.Strategy.PaymentStrategy;
import org.example.design_pattern.Strategy.PaymentStrategyFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class DesignPatternApplicationTests {


    @Autowired
    private PaymentStrategyFactory factory;


    @Test
    public void testStrategy() {
        pay("alipay", 100);
        pay("wechat", 200);
        pay("bank", 300);
        pay("unknown", 400); // 测试异常
    }

    private void pay(String type, double amount) {
        try {
            PaymentStrategy strategy = factory.getStrategy(type);
            strategy.pay(amount);
        } catch (Exception e) {
            System.out.println("错误: " + e.getMessage());
        }
    }

}

5. 输出结果

使用支付宝支付:100.0 元
使用微信支付:200.0 元
使用银行卡支付:300.0 元
错误: 不支持的支付类型: unknown

JDK中的策略模式使用

策略模式(Strategy Pattern)在 Java 和 Spring 源码中被广泛使用

模块 类/接口 说明
排序 Comparator<T> 比较器是典型的策略模式,允许自定义排序逻辑
线程池 RejectedExecutionHandler 定义任务拒绝策略,比如CallerRunsPolicy、AbortPolicy 等
加密 CipherSpi 加密算法策略切换,如 AES、RSA
集合 Collections.sort(List, Comparator) 第二个参数就是策略
Runnable Runnable 可以把不同任务封装为不同策略对象

1. 排序

List<String> list = Arrays.asList("apple", "banana", "orange");

// 传入不同的比较策略
Collections.sort(list, (a, b) -> b.compareTo(a)); // 按降序排列
  • Comparator 就是一个策略接口;
  • Lambda 表达式是它的策略实现。

2. 线程池

public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

实现类如:

  • AbortPolicy(丢弃并抛异常)
  • CallerRunsPolicy(调用方策略)
  • DiscardOldestPolicy(丢弃最旧策略)
  • DiscardPolicy(丢弃策略)

Spring中的策略模式使用

模块 类/接口 说明
Bean 生命周期 InstantiationStrategy 定义如何实例化一个Bean(反射/CGlib代理等)
AOP AdvisorAdapter 适配不同类型的通知,如前置通知、后置通知
事务管理 PlatformTransactionManager 根据不同数据库/事务策略切换实现
消息转换 HttpMessageConverter 处理不同格式(JSON/XML)的消息
类型转换 Converter<S, T> 类型转换器(如 String -> Integer)
资源加载 ResourceLoader 加载文件、classpath资源,不同策略实现

1. InstantiationStrategy(Bean 实例化策略)

public interface InstantiationStrategy {
    Object instantiate(BeanDefinition bd, String beanName, BeanFactory owner) throws BeansException;
}

实现类如:

  • SimpleInstantiationStrategy(反射实例化)
  • CglibSubclassingInstantiationStrategy(CGLIB动态代理实例化)

在 Spring 容器创建 Bean 时,选择不同实例化策略

2. PlatformTransactionManager (事务管理策略)

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;
}
  • 不同数据库有不同策略实现:

  • DataSourceTransactionManager(JDBC场景)

  • JpaTransactionManager(JPA场景)

  • HibernateTransactionManager(Hibernate场景)

3. HttpMessageConverter(请求/响应消息转换器)

  • 用在 Spring MVC 处理 JSON、XML 请求:
public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> clazz, MediaType mediaType);
    boolean canWrite(Class<?> clazz, MediaType mediaType);
    T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
    void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}
  • 有很多具体实现:

    • MappingJackson2HttpMessageConverter(处理 JSON)

    • MappingJackson2XmlHttpMessageConverter(处理 XML)

    • StringHttpMessageConverter(处理文本)

根据 Content-Type 自动选择不同的策略!

posted @ 2025-04-26 15:32  Eiffelzero  阅读(36)  评论(0)    收藏  举报