Spring与设计模式实战之策略模式

Spring与设计模式实战之策略模式

引言

在现代软件开发中,设计模式是解决常见设计问题的有效工具。它们提供了经过验证的解决方案,帮助开发人员构建灵活、可扩展和可维护的系统。本文将探讨策略模式在Spring框架中的应用,并通过实际例子展示如何通过Spring的特性来实现和管理策略模式。

1. 策略模式(Strategy Pattern)的概述

策略模式是一种行为型设计模式,它允许定义一系列算法,并将每个算法封装起来,使它们可以互换。这种模式让算法的变化独立于使用算法的客户。在Java中,策略模式通常通过接口和它们的实现类来实现。

1.1 策略模式的结构

  • 策略接口:声明了所有具体策略类都必须实现的操作。
  • 具体策略类:实现了策略接口,定义了具体的算法。
  • 上下文类:维护一个对策略对象的引用,并在需要时调用策略对象的方法。

2. ApplicationContextAware接口的介绍

在Spring框架中,ApplicationContext是一个非常核心的概念。它代表Spring IoC容器,负责实例化、配置和管理Beans。通过实现ApplicationContextAware接口,Spring Bean可以访问Spring的ApplicationContext,从而获取其他Beans或上下文信息。

2.1 ApplicationContextAware的使用

当一个Bean实现ApplicationContextAware接口时,Spring会在初始化该Bean时自动调用其setApplicationContext方法,并传入ApplicationContext实例。这样,该Bean就可以使用这个上下文来获取其他Beans或与Spring容器交互。

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class MyBean implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void doSomething() {
        // 使用applicationContext获取其他Bean
        AnotherBean anotherBean = applicationContext.getBean(AnotherBean.class);
        anotherBean.performTask();
    }
}

3. StrategyFactory的设计与实现

StrategyFactory是一个策略工厂类,负责根据业务需求创建和提供策略实例。它使用自定义的@TradeStrategy注解来识别和创建具体的策略类实例。

3.1 自定义注解@TradeStrategy

我们首先定义一个自定义注解@TradeStrategy,用于标注具体的策略类。这个注解可以在运行时通过反射机制进行处理。

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TradeStrategy {
    String value();
}

3.2 StrategyFactory的实现

StrategyFactory使用Spring的ApplicationContext来动态地获取所有添加了@TradeStrategy注解的Beans,并根据业务编码获取具体的策略类实例。

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

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

@Component
public class StrategyFactory {

    @Autowired
    private ApplicationContext applicationContext;

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

    @PostConstruct
    public void init() {
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(TradeStrategy.class);
        for (Object bean : beansWithAnnotation.values()) {
            TradeStrategy tradeStrategy = bean.getClass().getAnnotation(TradeStrategy.class);
            strategyMap.put(tradeStrategy.value(), (ITradeStrategy) bean);
        }
    }

    public ITradeStrategy getStrategy(String code) {
        return strategyMap.get(code);
    }
}

4. TradeStrategyContext的角色

TradeStrategyContext充当策略上下文的角色,提供获取策略实例的方法。它包含一个tradeStrategyMap,用于存储策略枚举和对应的策略实现。

4.1 TradeStrategyContext的实现

TradeStrategyContext依赖于StrategyFactory来获取策略实例,并提供一个统一的方法来执行策略。

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

@Component
public class TradeStrategyContext {

    @Autowired
    private StrategyFactory strategyFactory;

    public void executeStrategy(String code) {
        ITradeStrategy strategy = strategyFactory.getStrategy(code);
        if (strategy != null) {
            strategy.process();
        } else {
            throw new IllegalArgumentException("No strategy found for code: " + code);
        }
    }
}

5. ITradeStrategy接口及其实现

ITradeStrategy是一个策略接口,声明了一个process方法,所有具体策略类都需要实现这个接口。

5.1 ITradeStrategy接口

public interface ITradeStrategy {
    void process();
}

5.2 具体策略类的实现

以下是几个具体策略类的实现示例:

import org.springframework.stereotype.Component;

@TradeStrategy("apply")
@Component
public class ApplyServiceStrategy implements ITradeStrategy {
    @Override
    public void process() {
        System.out.println("Processing apply service strategy");
    }
}

@TradeStrategy("redeem")
@Component
public class RedeemServiceStrategy implements ITradeStrategy {
    @Override
    public void process() {
        System.out.println("Processing redeem service strategy");
    }
}

@TradeStrategy("convert")
@Component
public class CovertServiceStrategy implements ITradeStrategy {
    @Override
    public void process() {
        System.out.println("Processing convert service strategy");
    }
}

@TradeStrategy("withdraw")
@Component
public class WithDrawServiceStrategy implements ITradeStrategy {
    @Override
    public void process() {
        System.out.println("Processing withdraw service strategy");
    }
}

6. TradeController的设计

TradeController是交易请求的统一入口,提供了一个tradeIndex方法来处理交易请求。它使用TradeStrategyContext来获取并执行相应的策略。

6.1 TradeController的实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TradeController {

    @Autowired
    private TradeStrategyContext tradeStrategyContext;

    @GetMapping("/trade")
    public String tradeIndex(@RequestParam String code) {
        tradeStrategyContext.executeStrategy(code);
        return "Trade executed successfully for strategy: " + code;
    }
}

7. 策略的动态加载与维护

通过Spring的ApplicationContextStrategyFactory可以动态地获取所有添加了@TradeStrategy注解的Beans,并根据业务编码获取具体的策略类实例。这使得系统在添加新的策略时,只需要添加新的策略类并标注@TradeStrategy注解即可,无需修改现有代码。

8. 策略的扩展性

通过自定义注解和策略工厂,系统可以很容易地添加新的策略,而不需要修改现有的代码,提高了系统的扩展性。例如,当需要添加一个新的交易策略时,只需要创建一个新的策略类并标注@TradeStrategy注解,然后在需要时通过业务编码来调用该策略。

8.1 添加新策略的示例

@TradeStrategy("newStrategy")
@Component
public class NewServiceStrategy implements ITradeStrategy {
    @Override
    public void process() {
        System.out.println("Processing new service strategy");
    }
}

总结

策略模式在Spring框架中的应用展示了设计模式的强大和灵活性。通过自定义注解和Spring的ApplicationContext,我们可以实现策略的动态管理和扩展。这种方法不仅提高了代码的可维护性,还增强了系统的可扩展性。在实际项目中,合理地应用设计模式和Spring特性,可以显著提升系统的设计质量和开发效率。

附一张基金代销渠道订单处理流程图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/802440.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ | Leetcode C++题解之第240题搜索二维矩阵II

题目&#xff1a; 题解&#xff1a; class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int m matrix.size(), n matrix[0].size();int x 0, y n - 1;while (x < m && y > 0) {if (matrix[x][y] targ…

LabVIEW异步和同步通信详细分析及比较

1. 基本原理 异步通信&#xff1a; 原理&#xff1a;异步通信&#xff08;Asynchronous Communication&#xff09;是一种数据传输方式&#xff0c;其中数据发送和接收操作在独立的时间进行&#xff0c;不需要在特定时刻对齐。发送方在任何时刻可以发送数据&#xff0c;而接收…

AI自动生成PPT哪个软件好?高效制作PPT优选这4个

7.15初伏的到来&#xff0c;也宣告三伏天的酷热正式拉开序幕~在这个传统的节气里&#xff0c;人们以各种方式避暑纳凉&#xff0c;享受夏日的悠闲时光。 而除了传统的避暑活动&#xff0c;我们还可以用一种新颖的方式记录和分享这份夏日的清凉——那就是通过PPT的方式将这一传…

【Linux】权限管理与相关指令

文章目录 1.权限、文件权限、用户文件权限的理解以及对应八进制数值表示、设置目录为粘滞位文件类型 2.权限相关的常用指令susudochmodchownchgrpumaskwhoamifile 1.权限、文件权限、用户 通过一定条件&#xff0c;拦住一部分人&#xff0c;给另一部分权利来访问资源&#xff0…

Amazon EC2 部署Ollama + webUI

最近和同事闲聊&#xff0c;我们能不能内网自己部署一个LLM&#xff0c;于是便有了Ollama webUI的尝试 对于Linux&#xff0c;使用一行命令即可 curl -fsSL https://ollama.com/install.sh | shollama --help Large language model runnerUsage:ollam…

【Dison夏令营 Day 21】用Python编写绘图

绘画 - 在屏幕上绘制线条和形状。单击标记形状的起点&#xff0c;再次单击标记形状的终点。可使用键盘选择不同的形状和颜色。 """Paint, for drawing shapes.Exercises1. Add a color. 2. Complete circle. 3. Complete rectangle. 4. Complete triangle. 5. A…

大厂面试官问我:为什么Redis的rehash采用渐进式,而Java的hashmap是一次性rehash?【后端八股文十二:Redis hash八股文合集】

本文为【Redis hash八股文合集】初版&#xff0c;后续还会进行优化更新&#xff0c;欢迎大家关注交流~ hello hello~ &#xff0c;这里是绝命Coding——老白~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏…

PostgreSQL使用(二)

说明&#xff1a;本文介绍PostgreSQL的DML语言&#xff1b; 插入数据 -- 1.全字段插入&#xff0c;字段名可以省略 insert into tb_student values (1, 张三, 1990-01-01, 88.88);-- 2.部分字段插入&#xff0c;字段名必须写全 insert into tb_student (id, name) values (2,…

Windows 11几个常用的快捷键

WinQ/WinS&#xff1a;快速打开一键搜索 WinCtrlD&#xff1a;快速新建虚拟桌面。可以通过四根手指在触摸板划动进行切换&#xff0c;也可以通过WinTAB进行虚拟桌面切换 WinTAB&#xff1a;虚拟桌面切换 WinA&#xff1a;打开快速设置面板 WinD&#xff1a;快速切换到桌面&a…

springboot+vue+mybatis鲜花管理系统+PPT+论文+讲解+售后

随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;鲜花管理系统当然也不能排除在外。鲜花管理系统是以实际运用为开发背景&#xff0c;运用软件工程开发方法&#xff0c;采用SSM技…

如何建设微模块数据中心机房

建设微模块数据中心机房涉及多个步骤和技术要点&#xff0c;以下是基于现代技术和行业最佳实践的建设流程概览&#xff1a; 1. 需求分析与规划 确定需求&#xff1a;分析业务需求&#xff0c;包括IT容量、电力、冷却和空间需求。 选址评估&#xff1a;选择靠近关键基础设施的位…

秋招突击——7/16——复习{滑动窗口——无重复最长子串}——新作{相交链表,环形链表,滑动窗口——找到字符串中所有字母异位词}

文章目录 引言模板——滑动窗口/双指针复习无重复最长子串复习实现 新作相交链表个人实现参考实现 环形链表个人实现参考实现——快慢指针 找到字符串中所有字母的异位词个人实现参考实现 总结 引言 今天本来想完成指标的&#xff0c;但是做着做着&#xff0c;发现大部分做的比…

Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,zookeeper基本管理及kafka单点部署实战

Day07-ES集群加密&#xff0c;kibana的RBAC实战&#xff0c;zookeeper集群搭建&#xff0c;zookeeper基本管理及kafka单点部署实战 0、昨日内容回顾:1、基于nginx的反向代理控制访问kibana2、配置ES集群TSL认证:3、配置kibana连接ES集群4、配置filebeat连接ES集群5、配置logsta…

用go实现限流算法

文章目录 固定窗口优缺点&#xff1a;适用场景&#xff1a;总结&#xff1a; 滑动窗口优缺点&#xff1a;适用场景&#xff1a;总结&#xff1a; 漏桶限流器优缺点&#xff1a;适用场景&#xff1a;总结&#xff1a; 令牌桶优缺点&#xff1a;适用场景&#xff1a;总结&#xf…

保障低压设备安全!中国星坤连接器精密工艺解析!

在现代电子设备中&#xff0c;连接器扮演着至关重要的角色&#xff0c;它们是电子系统之间沟通的桥梁。随着技术的发展&#xff0c;对连接器的需求也在不断提升&#xff0c;特别是在低电压应用领域。中国星坤最新推出的低压连接器&#xff0c;以其精密性和安全性&#xff0c;为…

AI算法18-最小角回归算法Least Angle Regression | LARS

​​​ 最小角回归算法简介 最小角回归&#xff08;Least Angle Regression, LAR&#xff09;是一种用于回归分析的统计方法&#xff0c;它在某些方面类似于最小二乘回归&#xff0c;但提供了一些额外的优点。最小角回归由Bradley Efron等人提出&#xff0c;主要用于处理具有…

10.1 标注、注记图层和注记整体说明

文章目录 前言标注、注记图层和注记QGis中的标注QGis中的注释(Annotation)图层QGis中的注记 总结 前言 介绍标注、注记图层和注记说明&#xff1a;文章中的示例代码均来自开源项目qgis_cpp_api_apps 标注、注记图层和注记 有时地图需要使用一些文字信息说明其中的地理要素或其…

如何用一个例子向10岁小孩解释高并发实时服务的单线程事件循环架构

I/O密集型进程和CPU密集型进程 聊天应用程序、MMO&#xff08;大型多人在线&#xff09;游戏、金融交易系统、等实时服务需要处理大量并发流量和实时数据。 这些服务是I/O密集型的&#xff0c;因为它们花费大量资源处理输入输出操作&#xff0c;例如高吞吐量、低延迟网络通信…

泉盛UV-K5扩容2Mbit EEPROM

泉盛UV-K5扩容2Mbit EEPROM 步骤 分离前面板与背板。 拆下电池&#xff0c;底部有个空隙&#xff0c;从缝隙撬开背板。分离前面板时注意喇叭连接线&#xff0c;不要扯断了。 分离屏幕。 先从箭头位置向上挑起&#xff0c;屏幕稍微松动即可左右晃动&#xff0c;直至完全取出。注…

leetcode日记(40)N皇后

一开始没看到不能同斜线&#xff0c;以为只要不同行不同列就行&#xff0c;本来想先列出每一行的Q都不同位置的棋盘然后进行排列组合就行&#xff0c;后来才发现还有限制&#xff08;后来又想了一下&#xff0c;感觉可以先用这种思路然后去除有同一斜线的棋盘摆列&#xff09; …