当前位置: 首页 > news >正文

设计模式-服务定位器模式

设计模式-服务定位器模式

  • 一、背景
    • 1.1 服务定位模式
    • 1.2 策略模式
  • 二、代码实战
    • 2.1 服务定位器
    • 2.2 配置ServiceLocatorFactoryBean
    • 2.3 定义一个支付的接口
    • 2.4 根据不同类型处理Bean
    • 2.5 controller层
  • 三、项目结构及测试结果
    • 3.1 测试结果
    • 3.2 项目结构及源码(欢迎star)
  • 四、参考资料

一、背景

项目开发中如果让你设计支付模块,目前有支付宝、微信、各大银行的部分,你会如何设计支付这块的代码?在调用的客户端一般都是用if else去做判断,比如类型等于ALIPAY,我就用支付宝的实现逻辑处理。那如果新加一种支付方式,是不是调用的客户端还要修改呢?这显然太耦合了,更高级一点,可以用策略模式去实现。这篇博文使用“策略模式的升级版本”,服务定位模式Service Locator Pattern来解决,它帮助我们消除紧耦合实现及其依赖性,并提出将服务与其具体类解耦。

1.1 服务定位模式

服务定位器模式(Service Locator Pattern)属于J2EE 模式。用在我们想使用 JNDI 查询定位各种服务的时候,考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术。在首次请求某个服务时,服务定位器在 JNDI 中查找服务,并缓存该服务对象。当再次请求相同的服务时,服务定位器会在它的缓存中查找,这样可以在很大程度上提高应用程序的性能。以下是这种设计模式的实体。

(1)服务(Service) - 实际处理请求的服务。对这种服务的引用可以在 JNDI 服务器中查找到。
(2)Context / 初始的Context - JNDI Context 带有对要查找的服务的引用。
(3)服务定位器(Service Locator) - 服务定位器是通过JNDI 查找和缓存服务来获取服务的单点接触。
(4)缓存(Cache) - 缓存存储服务的引用,以便复用它们。
(5)客户端(Client) -Client 是通过 ServiceLocator 调用服务的对象。

1.2 策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
主要解决: 在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用: 一个系统有许多许多类,而区分它们的只是他们直接的行为。
应用实例:
诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
旅行的出游方式,选择骑自行车. 坐汽车,每一种旅行方式都是一个策略。
JAVA AWT 中的 LayoutManager。
优点:
算法可以自由切换。
避免使用多重条件判断。
扩展性良好。
缺点:
策略类会增多。
所有策略类都需要对外暴露。
使用场景:
如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。一个系统需要动态地在几种算法中选择一种
如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

二、代码实战

2.1 服务定位器

服务定位器接口PayParserFactory, 它有一个接受内容类型参数并返回PayService的方法。

package com.it.service;import org.springframework.stereotype.Component;/*** @description: 支付服务定位器工厂接口*/
@Component
public interface PayParserFactory {/*** 服务定位器* @param payType 支付类型* @return 返回具体的支付处理实现类*/PayService getPayParser(String payType);
}

2.2 配置ServiceLocatorFactoryBean

通过创建配置类,配置ServiceLocatorFactoryBean使用PayParserFactory作为服务定位器接口,PayParserFactory这个接口不需要写实现类。

package com.it.config;import com.it.service.PayParserFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ServiceLocatorFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @description: 支付解析器配置*/
@Configuration
public class PayParserConfig {/*** 初始化 payParserFactory bean* @return*/@Bean("payParserFactory")public FactoryBean serviceLocatorFactoryBean() {ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();// 设置服务定位接口factoryBean.setServiceLocatorInterface(PayParserFactory.class);return factoryBean;}
}

2.3 定义一个支付的接口

package com.it.service;/*** @description: 支付服务接口*/
public interface PayService {//支付接口boolean pay(String orderId);
}

2.4 根据不同类型处理Bean

设置解析器Bean的名称为类型名称,方便服务定位。
支付宝支付

package com.it.service.impl;import com.it.service.PayService;
import org.springframework.stereotype.Component;/*** @description: 支付宝支付实现层*/
@Component("AliPay")
public class AliPayServiceImpl implements PayService {@Overridepublic boolean pay(String orderId) {System.out.println("支付宝支付-----------------------");return true;}
}

微信支付

package com.it.service.impl;import com.it.service.PayService;
import org.springframework.stereotype.Component;/*** @description: 微信支付实现层*/
@Component("WxPay")
public class WxPayServiceImpl implements PayService {@Overridepublic boolean pay(String orderId) {System.out.println("微信支付-----------------------");return true;}
}

2.5 controller层

package com.it.controller;import com.it.service.PayParserFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** @description: 支付模块控制层*/
@RestController
@RequestMapping("/pay")
public class PayController {@Autowiredprivate PayParserFactory payParserFactory;@PostMapping("/orderPay")public boolean orderPay(@RequestParam String payType) {// 关键点,直接根据类型获取boolean result = payParserFactory.getPayParser(payType).pay("P202303013475492");return result;}
}

总结:
Spring 的ServiceLocatorFactoryBean实现了 FactoryBean接口,创建了Service Factory服务工厂Bean。我们通过使用服务定位器模式实现了一种扩展 Spring 控制反转的方法。它帮助我们解决了依赖注入未提供最佳解决方案的用例。也就是说,依赖注入仍然是首选,并且在大多数情况下不应使用服务定位器来替代依赖注入。

三、项目结构及测试结果

3.1 测试结果

输入localhost:9003/pay/orderPay?payType=WxPay
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 项目结构及源码(欢迎star)

在这里插入图片描述
源码下载springboo-cacheable,欢迎star!

四、参考资料

设计模式
设计模式简要介绍
服务定位器模式
设计模式-策略模式(服务定位器模式)
设计模式-服务定位器模式

相关文章:

设计模式-服务定位器模式

设计模式-服务定位器模式一、背景1.1 服务定位模式1.2 策略模式二、代码实战2.1 服务定位器2.2 配置ServiceLocatorFactoryBean2.3 定义一个支付的接口2.4 根据不同类型处理Bean2.5 controller层三、项目结构及测试结果3.1 测试结果3.2 项目结构及源码(欢迎star)四、参考资料一…...

Android Dalvik虚拟机 GC流程分析

前言 本篇继续介绍安卓dalvik虚拟机,介绍Dalvik虚拟技的GC流程。 GC结构体 dalvik/vm/alloc/Heap.h static const GcSpec kGcForMallocSpec {true, /* isPartial */false, /* isConcurrent */true, /* doPreserve */"GC_FOR_ALLOC" }; /* Not eno…...

opencv读入图片注意事项

来源:投稿 作者:蓬蓬奇 编辑:学姐 深度学习数据预处理中常用opencv读入图片,一般在__getitem__函数中调用。本文主要介绍opencv读取图片的一些细节以及注意事项。本文中使用的图片见第6节“opencv测试使用的图片”。 1.如何通过o…...

学习渗透测试,考CISP-PTE还是考NISP-PT证书呢?

其实两者都可以,但是要看考生的实际需求! 为什么说两者都可以? 两个证书都由中国信息安全测评中心颁发,CISP-PTE(注册信息安全渗透测试工程师),NISP-PT(国家信息安全水平考试渗透测试工程师),…...

记录自己遇到的关于Hashmap的面试题

一.麻烦讲述一下Hashmap的扩容原理 jdk1.8中的hashmap扩容原理 1.put流程图 首先贴一张图(图片来源于传送门),多谢大佬的美图,此图已经完美的描述了put的整个流程,我也就不想自己画了,嘿嘿: 2.hashmap中几个比较重…...

mysql数据库之sql语句性能分析工具

一、sql执行频率。 mysql客户端连接成功后,通过show [session | global] status 命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT/UPDATE/DELETE的访问频次。 #一个下划线代表一个字符 show global status like com_; 二、慢查…...

搭建SpringBoot项目

文章目录前言准备工具创建项目前言 为什么使用SpringBoot?它有什么好处? SpringBoot可以快速构建出独立的Spring应用,简化了配置文件。内嵌Tomcat服务器,无须手动部署war文件。 准备工具 idea2022navicat16postmanjdk1.8 创建项目 File-&…...

“一网统管”视频融合平台EasyCVR页面tab切换细节优化

EasyCVR视频融合平台基于云边端协同架构,能支持海量视频的轻量化接入与汇聚管理,借助大数据分析的决策判断,为网络摄像头、网络存储设备、智能终端、无人机、车载设备、移动执法仪、视频监控平台等提供一体化的视频接入、分发、存储、处理等能…...

【Python入门第二十天】Python Lambda

lambda 函数是一种小的匿名函数。 lambda 函数可接受任意数量的参数,但只能有一个表达式。 语法 lambda arguments : expression执行表达式并返回结果: 实例 一个 lambda 函数,它把作为参数传入的数字加 10,然后打印结果&…...

比特数据结构与算法(第四章_下)二叉树OJ(力扣:144,965,104,226,100,572)

144. 二叉树的前序遍历难度简单给你二叉树的根节点 root ,返回它节点值的 前序 遍历。示例 1:输入:root [1,null,2,3]输出:[1,2,3]示例 2:输入:root [ ]输出:[ ]示例 3:输入&#…...

【C++】inline 内联函数

文章目录📕 概念📕 使用前的准备📕 使用📕 特性📕 概念 在 C 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表…...

如何审计一个智能合约

智能合约审计用于整个 DeFi 生态系统,通过对协议代码的深入审查,可以帮助解决识别错误、低效代码以及这些问题。智能合约具有不可篡改的特点,这使得审计成为任何区块链项目安全流程的关键部分。 代码审计对任何应用程序都很重要,…...

不用PS,也能实现抠图的工具

对于非设计专业的同学来说,专门下载 PS 抠图有点大材小用,而且运用 PS 对电脑配置一定要求。不过现在有了更多选择,市面上出现了越来越多的抠图软件,不过越多的抠图软件选择也意味着需要花费时间试错因此本文将给大家推荐 3 款非常…...

集群化存储的概述

集群化存储的概述 1、存储的分类方式: 存储的分类-网络拓扑 用于存储的网络拓扑 NAS:小米路由器;SAN:存储区网络–>网络网和存储网络区分开DAS:常见的存储;本地存储 存储分类-存储技术网络拓扑存储技…...

asyncio 并发编程(一)

Python2 时代高性能的网络编程主要是 Twisted、Tornado 和 Gevent 这三个库,但是它们的异步代码相互之间既不兼容也不能移植。Gvanrossum 希望在 Python 3 实现一个原生的基于生成器的协程库,其中直接内置了对异步 IO 的支持,这就是 asyncio&…...

春招冲刺(二):BFC 盒子面试题总结

BFC 盒子面试题总结 Q1:BFC盒子是什么? BFC全称是Block Formatting Context 意思就是块级格式化上下文。 可以把BFC看做一个容器,容器里边的元素不会影响到容器外部的元素。 Q2:如何创建BFC? 根元素:bo…...

Ep_计网面试题-本地IP地址怎么一层层向上转换?

将数据加上报头打包在一起形成新的数据包继续往下一层传递。拆包的时候就是把数据包去掉包头作为新数据传给上一层 视频讲解: https://edu.csdn.net/course/detail/38090 点我进入 面试宝典 很多人不知道面试问什么,或者其他的XXGuide,那里边的太多没用的,也没有源码解析,都…...

MySQL高级三

目录 三、MySQL高级03 3.1 MyCat 3.1.1 MyCat简介 3.1.2 中间件的作用 3.2 安装MyCat 3.3 主从复制 3.3.1 主从复制的原理 3.3.2 主从复制的好处 3.3.3 配置主从复制 三、MySQL高级03 如果虚拟机的磁盘已满,可以对磁盘进行重新分配 参考:虚拟…...

set和map的基本使用

目录 关联式容器 要点分析 键值对 pair介绍 set 模板参数列表: set的构造: 常用接口 操作 multiset map map的构造 插入 make_pair map的迭代器 operator[] multimap multimap中为什么没有重载operator[] 关联式容器 关联式容器也是用…...

已解决pip install wxPython模块安装失败

已解决(pip install wxPython安装失败)error: legacy-instal1-failure Encountered error while trying to install package.wxPython note: This is an issue with the package mentioned above,not pip. hint : See above for output from …...

Linux基础——连接Xshell7

个人简介:云计算网络运维专业人员,了解运维知识,掌握TCP/IP协议,每天分享网络运维知识与技能。座右铭:海不辞水,故能成其大;山不辞石,故能成其高。个人主页:小李会科技的…...

C++——智能指针1

目录 RAII auto_ptr模拟实现 智能指针拷贝问题 唯一指针 shared_ptr(可以拷贝) shared_ptr模拟实现 完整代码 循环引用 weak_ptr模拟实现 定制删除器 shared_ptr定制删除器模拟实现 内存泄漏 RAII RAII(Resource Acquisit…...

[数据集][VOC][目标检测]翻越栏杆翻越防护栏数据集目标检测可用yolo训练-1035张介绍

数据集格式:Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件,仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数):1035 标注数量(xml文件个数):1035 标注类别数:2 标注类别名称:["fylg","…...

深度学习 | BN层原理浅谈

深度学习 | BN层原理浅谈 文章目录深度学习 | BN层原理浅谈一. 背景二. BN层作用三. 计算原理四. 注意事项为什么BN层一般用在线性层和卷积层的后面,而不是放在激活函数后为什么BN能抑制过拟合(有争议)一. 背景 神经网络在训练时,由于内存限制&#xff0…...

每日面试题

2022/12/15 如何实现一个IOC容器 1、配置文件配置包扫描路径 2、递归包扫描获取.class文件 3、反射、确定需要交给lOC管理的类4、对需要注入的类进行依赖注入 配置文件中指定需要扫描的包路径 定义一些注解,分别表示访问控制层、业务服务层、数据持久层、依赖注…...

将IDEA的项目托管到gitee

目录1. 在gitee上创建仓库2. 本地创建仓库目录3. 将项目添加到缓冲区4. 将缓冲区的项目添加到本地仓库5. 将本地仓库的项目上传到gitee6. 遇到的问题6.1 问题描述6.2 解决方法7. 相关图示与补充8. 相关参考1. 在gitee上创建仓库 2. 本地创建仓库目录 在IDEA中选择创建 Git 仓…...

父类子类静态代码块、构造代码块、构造方法执行顺序

github:https://github.com/nocoders/java-everything.git 名词解释 静态代码块:java中使用static关键字修饰的代码块,每个代码块只会执行一次,JVM加载类时会执行静态代码块中的代码,静态代码块先于主方法执行。构造代码块&#…...

【C++】开散列实现unordered_map与unordered_set的封装

本文主要介绍unordered_map与unordered_set的封装,此次封装主要用上文所说到的开散列,通过开散列的一些改造来实现unordered_map与unordered_set的封装 文章目录一、模板参数二、string的特化三、正向迭代器四、构造与析构五、[]的实现六、unordered_map的实现七、u…...

华为OD机试真题Python实现【删除指定目录】真题+解题思路+代码(20222023)

删除指定目录 题目 某文件系统中有 N 个目录, 每个目录都一个独一无二的 ID。 每个目录只有一个付目录, 但每个目录下可以有零个或多个子目录, 目录结构呈树状结构。 假设 根目录的 ID 为0,且根目录没有父目录 ID 用唯一的正整数表示,并统一编号 现给定目录 ID 和其付目…...

CSS选择器大全(上)

基础选择器: id选择器:#id{} 类选择器: .class{} 标签选择器: h1{} 复合选择器: 交集选择器:作用:选中同时符合多个条件的元素 语法:选择器1选择器2选择器3选择器n{} 注意&#xff…...