您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

使用 Spring 实现策略模式可以这么简单

时间:2022-02-09 10:05:52  来源:  作者:DNF搬砖摸金达人

最近看同事的代码时候,学到了个小技巧,在某些场景下非常挺有用的,这里分享一下给大家。

使用 Spring 实现策略模式可以这么简单

 

Spring 中 @Autowired注解,大家应该不会陌生,用过 Spring 的肯定也离不开这个注解,通过这个注解可以帮我们自动注入我们想要的 Bean。

除了这个基本功能之外,@Autowired 还有更加强大的功能,还可以注入指定类型的数组,List/Set 集合,甚至还可以是 Map 对象。

比如说当前应用有一个支付接口 PayService,分别需要对接支付宝、微信支付、银行卡,所以分别有三个不同实现类 AliPayService,WechatPayservice,BankCardPayService。

四个类的关系如下图所示:

使用 Spring 实现策略模式可以这么简单

 

如果此时我需要获取当前系统类所有 PayService Bean,老的方式我们只能通过 BeanFactory或者 ApplicationContext 获取。

// 首先通过 getBeanNamesForType 获取 PayService 类型所有的 Bean
String[] names = ctx.getBeanNamesForType(PayService.class);
List<PayService> anotherPayService = Lists.newArrayList();
for (String beanName : names) {
    anotherPayService.add(ctx.getBean(beanName, PayService.class));
}
// 或者通过 getBeansOfType 获取所有 PayService 类型
Map<String, PayService> beansOfType = ctx.getBeansOfType(PayService.class);
for (Map.Entry<String, PayService> entry : beansOfType.entrySet()) {
    anotherPayService.add(entry.getValue());
}

但是现在我们可以不用这么麻烦了,我们可以直接使用 @Autowired 注入 PayService Bean 数组,或者 PayService List/Set 集合,甚至,我们还可以注入 PayService 的 Map 集合。

@Autowired
List<PayService> payServices;

@Autowired
PayService[] payServicesArray;
使用 Spring 实现策略模式可以这么简单

 

知道了这个功能,当我们需要使用 Spring 实现策略模式就非常简单。

可能有的小伙伴不太了解策略模式,没关系,这类阿粉介绍一个业务场景,通过这个场景给大家介绍一下策略模式。

还是上面的例子,我们当前系统需要对接微信支付、支付宝、以及银行卡支付。

当接到这个需求,我们首先需要拿到相应接口文档,分析三者的共性。

假设我们这里发现,三者模式比较类似,只是部分传参不一样。

所以我们根据三者的共性,抽象出一组公共的接口 PayService,

public interface PayService {
    PayResult epay(PayRequest request);
}

然后分别实现三个实现类,都继承这个接口。

那么现在问题来了,由于存在三个实现类,如何选择具体的实现类?

其实这个问题很好解决,请求参数传入一个唯一标识,然后我们根据标识选择相应的实现类。

比如说我们在请求类 PayRequest 搞个 channelNo 字段,这个代表相应支付渠道唯一标识,比如说支付宝为:00000001,微信支付为 00000002,银行卡支付为 00000003

接着我们需要把唯一标识与具体实现类一一映射起来,刚好我们可以使用 Map 存储这种映射关系。

我们实现一个 RouteService,具体代码逻辑如下:

@Service
public class RouteService {

    @Autowired
    Map<String, PayService> payServiceMap;

    public PayResult epay(PayRequest payRequest) {
        PayService payService = payServiceMap.get(payRequest.getChannelNo());
        return  payService.epay(payRequest);
    }

}

我们在 RouteService 自动注入 PayService 所有相关 Bean,然后使用唯一标识查找实现类。

这样我们对外就屏蔽了支付渠道的差异,其他服务类只要调用 RouteService 即可。

但是这样实现还是有点小问题,由于我们唯一标识为一串数字,如果像我们上面直接使用 @Autowired注入 Map,这就需要我们实现类的 Bean 名字为 00000001 这些。

但是这样命名不是很优雅,这样会让后来同学很难看懂,不好维护。

所以我们需要做个转换,我们可以这么实现。

首先我们改造一下 PayService 这个接口,增加一个方法,每个具体实现类通过这个方法返回其唯一标识。

public interface PayService {

    PayResult epay(PayRequest request);

    String channel();
}

具体举个支付宝实现类的代码,其他实现类实现类似。

@Service("aliPayService")
public class AliPayService implements PayService {

    @Override
    public PayResult epay(PayRequest request) {
        // 业务逻辑
        return new PayResult();
    }
    @Override
    public String channel() {
        return "00000001";
    }
}

最后我们改造一下 RouteService,具体逻辑如下:

@Service
public class RouteService {

    @Autowired
    Set<PayService> payServiceSet;
    
    Map<String, PayService> payServiceMap;

    public PayResult epay(PayRequest payRequest) {
        PayService payService = payServiceMap.get(payRequest.getChannelNo());
        return  payService.epay(payRequest);
    }

    @PostConstruct
    public void init() {
        for (PayService payService : payServiceSet) {
            payServiceMap = new HashMap<>();
            payServiceMap.put(payService.channel(), payService);
        }
    }
}

上面代码首先通过自动注入 PayService 一个集合,然后我们再将其转为一个 Map,这样内部存储刚好是唯一标识与实现类的映射了。

好了,今天的小技巧就分享到这里,学到小伙伴,不妨点个赞吧。



Tags:Spring   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
最近看同事的代码时候,学到了个小技巧,在某些场景下非常挺有用的,这里分享一下给大家。 Spring 中 @Autowired注解,大家应该不会陌生,用过 Spring 的肯定也离不开这个注解,通过这...【详细内容】
2022-02-09  Tags: Spring  点击:(3)  评论:(0)  加入收藏
目前线上很多SAAS系统,但是SAAS系统必须支持多租户,对于多租户有多种实现方式,当然不同的实现方式的成本也是不同的。这里我介绍一种最节省成本的实现方式,通过数据记录增加租户...【详细内容】
2022-01-10  Tags: Spring  点击:(32)  评论:(0)  加入收藏
1、什么是YAMLYAML是"YAML Ain&rsquo;t a Markup Language"(YAML不是一种标记语言)的递归缩写。YAML的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。主要强度...【详细内容】
2021-12-29  Tags: Spring  点击:(34)  评论:(0)  加入收藏
想要了解Spring MVC框架的原理,探究框架是如何设计的,不错的学习方式是阅读源码,然后自己手写一个框架。本文带领大家简化的手写一个Spring MVC框架。Spring框架对于Java后端程...【详细内容】
2021-09-22  Tags: Spring  点击:(68)  评论:(0)  加入收藏
前言一个基于spring boot的JAVA开源商城系统,是前后端分离、为生产环境多实例完全准备、数据库为b2b2c商城系统设计、拥有完整下单流程和精美设计的java开源商城系统https://...【详细内容】
2021-09-17  Tags: Spring  点击:(150)  评论:(0)  加入收藏
在 Java 和 Kotlin 中, 除了使用Spring Boot创建微服务外,还有很多其他的替代方案。 名称 版本 发布时间 开发商 GitHub ...【详细内容】
2021-08-06  Tags: Spring  点击:(226)  评论:(0)  加入收藏
大家都知道,MyBatis 框架是一个持久层框架,是 Apache 下的顶级项目。Mybatis 可以让开发者的主要精力放在 sql 上,通过 Mybatis 提供的映射方式,自由灵活的生成满足需要的 sql 语句。使用简单的 XML 或注解来配置和映射原...【详细内容】
2021-07-06  Tags: Spring  点击:(113)  评论:(0)  加入收藏
首先,先看 SpringBoot 的主配置类:@SpringBootApplicationpublicclassStartEurekaApplication{publicstaticvoidmain(String[] args){SpringApplication.run(StartEurekaAppli...【详细内容】
2021-06-11  Tags: Spring  点击:(152)  评论:(0)  加入收藏
环境:Spring5.3.3Spring容器启动时,创建 DefaultListableBeanFactory 工厂实例化 AnnotationConfigApplicationContext对象public AnnotationConfigApplicationContext(String...【详细内容】
2021-06-10  Tags: Spring  点击:(164)  评论:(0)  加入收藏
现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了...【详细内容】
2021-05-27  Tags: Spring  点击:(201)  评论:(0)  加入收藏
▌简易百科推荐
今天TJ君要给大家分享的是一款Mybatis界面工具,可以方便生成Mybatis的相关代码。mybatis-generator-guimybatis-generator-gui,是一款基于mybatis-generator开发的界面工具,目...【详细内容】
2022-02-10  码农看看    Tags:MyBatis   点击:(4)  评论:(0)  加入收藏
最近看同事的代码时候,学到了个小技巧,在某些场景下非常挺有用的,这里分享一下给大家。 Spring 中 @Autowired注解,大家应该不会陌生,用过 Spring 的肯定也离不开这个注解,通过这...【详细内容】
2022-02-09  DNF搬砖摸金达人    Tags:Spring   点击:(3)  评论:(0)  加入收藏
Spring控制反转IOC 控制反转IOC: Inversion of Control 是一种解耦设计原则 主要目的是借助第三方,比如Spring IOC容器实现具有依赖关系的对象之间的解耦,从而降低代码之间...【详细内容】
2022-02-09  Java架构海子    Tags:框架   点击:(3)  评论:(0)  加入收藏
GO 语言爱好者的最佳Web框架如果你是自己写一个小应用程序,那你可能不需要Web框架。但是如果你要做产品,那么你肯定需要一个好的框架。如果你认为你有相应的知识和经验,你会自...【详细内容】
2022-02-01  杨同学编程    Tags:Web框架   点击:(14)  评论:(0)  加入收藏
《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的是一个用 Python 编写的开源 UI 框架&mdash;&mdash;kiv...【详细内容】
2022-01-10  GitHub精选    Tags:UI 框架   点击:(35)  评论:(0)  加入收藏
Apache Dubbo 3.0.5 已发布,这是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用、智能容错和负载均衡,以及服务自动注册和发现。此版本...【详细内容】
2022-01-07  BAT架构    Tags:框架   点击:(30)  评论:(0)  加入收藏
微信支付API-V3和V2的区别微信支付API-V3和之前V2版本最大的区别,应该就是加密方式的改变了。新版的支付接口,全部使用是SSL双向加密。就是指微信服务器端、商户端各自都有一...【详细内容】
2021-12-29  666Tec    Tags:Springboot   点击:(30)  评论:(0)  加入收藏
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(53)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(47)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(34)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条