Spring小技巧之设计模式

Spring小技巧之设计模式

责任链模式

模式定义

  • 该模式在《图解设计模式》的第14章节《Chain of Responsibility模式》有详细的介绍。简单来说:当一个对象需要交给多个处理类依次处理的时候就可以用责任链模式,Servlet Filter、Spring 拦截器链都是这一模式的实际应用,在订单履约等业务场景中也经常使用到。

示例代码

  • OrderCreatedBaseHandler:责任链顶层接口定义类,所有处理器都实现该接口。

    java 复制代码
    package com.wwq.test;
    
    /**
     * 创建订单责任链接口
     */
    public interface OrderCreatedBaseHandler {
    
        /**
         * 运行消息处理
         */
        void run(Order order);
    
        /**
         * 是否执行</br>
         * 子类重写该方法,可根据配置开关,来确定是否执行 run 方法
         */
        default boolean isRun(Order order){
            return true;
        }
    
    }
  • OrderCreatedOperate:责任链执行器类,是整个责任链的管理容器和启动入口。利用Spring批量注入接口实现类为List的机制串联整个链条。

    java 复制代码
    package com.wwq.test;
    
    /**
     * 责任链执行器,运行所有 OrderCreatedBaseHandler 实现类
     */
    @Component
    public class OrderCreatedOperate {
    
        /*
         * 注入全部处理器
         */
        @Autowired
        private List<OrderCreatedBaseHandler>  baseOrderCreatedHandles;
    
        /**
         * 运行消息处理
         * @param orderCreatedMessage 订单创建消息
         */
        public void run(Order order) {
            for(OrderCreatedBaseHandler handler : baseOrderCreatedHandles){
               if(handler.isRun(order)){
                   handler.run(order);
               }
            }
        }
        
    }
  • 各个责任链处理,可通过@Order注解调整他们的执行顺序。

    java 复制代码
    package com.wwq.test;
    
    /**
     * 创建订单处理器
     */
    @Slf4j
    @Component
    public class OrderCreatedHandler implements OrderCreatedBaseHandler {
    
        public void run(OrderCreatedMessage orderCreatedMessage){
            // TODO 创建订单
        }
        
    }
    java 复制代码
    package com.wwq.test;
    
    /**
     * 积分处理器
     */
    @Slf4j
    @Component
    public class PointHandler implements OrderCreatedBaseHandler {
    
        public void run(OrderCreatedMessage orderCreatedMessage){
            // TODO 积分抵扣和发送
        }
        
    }
    java 复制代码
    package com.wwq.test;
    
    /**
     * 物流处理器
     */
    @Slf4j
    @Component
    public class LogisticsHandler implements OrderCreatedBaseHandler {
    
        public void run(OrderCreatedMessage orderCreatedMessage){
            // TODO 处理物流流程信息
        }
        
    }
    java 复制代码
    package com.wwq.test;
    
    /**
     * 商品库存处理器
     */
    @Slf4j
    @Component
    public class StockHandler implements OrderCreatedBaseHandler {
    
        public void run(OrderCreatedMessage orderCreatedMessage){
            // TODO 库存扣减
        }
        
    }
  • 如果想各个处理器并行执行,可以使用 CompletableFuture.runAsync() 提交异步任务。

    java 复制代码
    package com.wwq.test;
    
    /**
     * 责任链执行器,运行所有 OrderCreatedBaseHandler 实现类
     */
    @Component
    public class OrderCreatedOperate {
    
        /*
         * 责任链执行线程池
         */
        @Autowired
        @Qualifier("orderCreatedTaskExecutor")
        private Executor orderCreatedTaskExecutor;
    
        /*
         * 注入全部处理器
         */
        @Autowired
        private List<OrderCreatedBaseHandler>  baseOrderCreatedHandles;
    
        /**
         * 运行消息处理
         * @param orderCreatedMessage 订单创建消息
         */
        public void run(Order order) {
    
            /*
             * 收集 Future
             */
            List<CompletableFuture<?>> futures = new ArrayList<>();
    
            /*
             * 异步执行每个处理器
             */
            for(OrderCreatedBaseHandler handler : baseOrderCreatedHandles){
                futures.add(CompletableFuture.runAsync(() -> {
                    if(handler.isRun(order)){
                        handler.run(order);
                    }
                }, orderCreatedTaskExecutor));
            }
    
            /*
             * 等待所有异步任务全部执行完毕
             */
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        }
    
    }

策略模式模式

模式定义

  • 该模式在《图解设计模式》的第10章节《Strategy模式》有详细的介绍。当需要根据某种条件整体替换运算逻辑时就可以使用策略模式,在支付渠道、文件解析、报表导出、优惠计算等场景都有应用。

示例代码

  • 策略接口定义

    java 复制代码
    	public interface PayStrategy {
    	    // 渠道标识
    	    String getChannel();
    	    // 支付逻辑
    	    void pay(BigDecimal amount);
    	}
  • 策略实现

    java 复制代码
    @Component
    public class AliPayStrategy implements PayStrategy {
        @Override
        public String getChannel() {
            return "ALI";
        }
        @Override
        public void pay(BigDecimal amount) {
            System.out.println("支付宝支付:" + amount);
        }
    }
    java 复制代码
    @Component
    public class WxPayStrategy implements PayStrategy {
        @Override
        public String getChannel() {
            return "WX";
        }
        @Override
        public void pay(BigDecimal amount) {
            System.out.println("微信支付:" + amount);
        }
    }
  • 策略工厂

    java 复制代码
    @Service
    public class PayStrategyFactory {
        // 自动注入全部策略实现
        private final Map<String, PayStrategy> strategyMap;
    
        @Autowired
        public PayStrategyFactory(List<PayStrategy> payStrategies) {
            this.strategyMap = new HashMap<>();
            for(PayStrategy strategy : payStrategies){
                strategyMap.put(strategy.getChannel(), strategy);
            }
        }
    
        // 根据渠道获取对应策略
        public PayStrategy getStrategy(Integer channel) {
            return strategyMap.get(channel);
        }
    }
  • 使用策略

    java 复制代码
    @Autowired
    private PayStrategyFactory factory;
    
    public void test() {
        PayStrategy ali = factory.getStrategy("ALI");
        ali.pay(new BigDecimal("100"));
    }
相关推荐
weixin_436525076 小时前
Spring + Dubbo + Zookeeper项目依赖注入
spring·dubbo·java-zookeeper
L-影7 小时前
springboot启动流程
java·spring boot·spring
早川9197 小时前
有关线程池知识
spring
ShoreKiten7 小时前
SQL注入之SQL Server增删改查
数据库·sql
z落落9 小时前
SQL 表的基本操作 数据库增删改查(CRUD)+SQL 进阶语法详解(标识列插入、模糊查询、Union、变量、运算、别名)
数据库·sql
Larcher1 天前
当 AI 学会写代码:一个自动生成 React 项目的 Agent 实战
人工智能·设计模式·程序员
霸道流氓气质1 天前
Spring AI Alibaba Copilot 项目使用指南
人工智能·spring·copilot
码农阿豪1 天前
上线前能跑,上线后挂了,三个隐性的SQL陷阱
数据库·sql
空中湖1 天前
Spring AI 多模型接入实战:OpenAI、Ollama、通义千问切换只需改配置
java·人工智能·spring