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

设计模式之服务定位模式

文章目录

  • 服务定位器模式
    • 概要
      • 意图
      • 主要解决的问题
      • 使用场景
      • 实现方式
      • 关键代码
      • 应用实例
        • 优点
        • 缺点
      • 使用建议
      • 注意事项
      • 包含的几个主要角色
  • 代码实现

服务定位器模式

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

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

概要

意图

用于在应用程序中提供一个中心化的服务访问点,用以获取各种服务或资源。

主要解决的问题

解决在应用程序中需要访问各种服务或资源时,避免硬编码服务访问逻辑的问题。

使用场景

当应用程序需要访问多个外部服务或资源,并且希望将这些访问逻辑集中管理时。

实现方式

  • 服务定位器接口:定义获取服务的方法。
  • 服务定位器实现:实现服务定位器接口,封装服务的查找和访问逻辑。
  • 服务接口:定义服务的接口或契约。
  • 具体服务:实现服务接口,提供具体的服务功能。

关键代码

服务定位器:包含逻辑以查找和返回请求的服务实例。
服务接口:定义服务的抽象表示。

应用实例

企业应用程序:应用程序使用服务定位器来访问数据库服务、消息队列服务等。

优点
  • 解耦服务访问:将服务访问逻辑与使用服务的业务逻辑分离。
  • 集中管理:服务的访问点集中管理,便于维护和扩展。
  • 灵活性:易于添加、修改或替换服务。
缺点
  • 性能问题:服务定位器可能引入性能开销,特别是在每次服务请求都进行查找时。
  • 过度使用:可能导致设计模式的滥用,从而隐藏系统结构。

使用建议

当应用程序需要以一种灵活且可维护的方式访问多个服务时,考虑使用服务定位器模式。

注意事项

避免过度依赖服务定位器,因为它可能掩盖系统的依赖关系,使得调试和优化变得困难。

包含的几个主要角色

  • 服务定位器接口(Service Locator Interface): 定义获取服务的方法。
  • 服务定位器实现(Service Locator Implementation): 实现服务定位器接口,封装服务的查找和访问逻辑。
  • 服务接口(Service Interface): 定义服务的抽象表示。
  • 具体服务(Concrete Service): 实现服务接口,提供具体的服务功能。
  • 客户端(Client): 使用服务定位器来访问所需的服务。
  • Context /初始的Context - 初始化服务对象并提供对象索引。

服务定位器模式通过提供一个集中的服务访问点,有助于简化服务访问逻辑,并提高应用程序的灵活性和可维护性。

代码实现

这里以Spring的BeanFactory的逻辑举例,不涉及具体的xml的具体实现,只是把代码的结构表达出来

首先定义BeanFactory接口,相当于服务定位模式中的服务定位器(Service Locator)角色

public interface BeanFactory {Object getBean(String beanName);<T> T getBean(String beanName,Class<T> clzss);
}

然后定义对象注入接口,Spring框架中ApplicationContext,相当于服务定位模式中的Context

public interface ApplicationContext {//spring-beans.xml 配置文件的路径void init(String context);
}

具体实现Xml解析初始化,按照服务定位模式来说需要一个服务定位器(Service Locator)的角色的实现,也就是这里的BeanFatory的实现,但是Spring在实现中,通过一个实现两个接口同实现两个功能。

public class XmlApplicationContext implements ApplicationContext,BeanFactory{private Map<String,Object> cache = new HashMap<>();public XmlApplicationContext(String context){init(context);}@Overridepublic void init(String context) {//根据context 读取xml配置文件,初始化cache// 这里直接创建cache.put("userController",new UserController());}@Overridepublic Object getBean(String beanName) {return cache.get(beanName);}@Override@SuppressWarnings("unchecked")public <T> T getBean(String beanName, Class<T> clzss) {return (T) cache.get(beanName);}
}

定义服务角色

public interface Controller {void handle();
}
public class UserController implements Controller{@Overridepublic void handle() {System.out.println("处理请求");}
}

实际使用的过程

public class Client {public static void main(String[] args) {XmlApplicationContext xmlApplicationContext = new XmlApplicationContext("classpath:spring-beans.xml");Controller b = xmlApplicationContext.getBean("userController", Controller.class);}
}

相关文章:

  • 【机器学习】神经网络与深度学习:探索智能计算的前沿
  • 以太坊网络中为什么要设置Gas上限
  • 从零手写实现 nginx-23-nginx 对于 cookie 的操作
  • mysql的索引可以分为哪些类型
  • 编程后端:深入探索其所属的行业领域
  • Petalinux由于网络原因产生的编译错误(2)--Fetcher failure:Unable to find file
  • 技术革命的十年:计算机、互联网、大数据、云计算与AI
  • 基于GTX 8B10B编码的自定义PHY上板测试(高速收发器十四)
  • 【Linux】基础IO——文件描述符,重定向
  • web前端设计界面:深度解析与创意实践
  • OpenCV 的模板匹配
  • cuda-cuda语法
  • 【Java并发编程之美 | 第一篇】并发编程线程基础
  • 【AI工具】jupyter notebook和jupyterlab对比和安装
  • 【Linux】高级IO——五种IO方式,select,poll,epoll
  • SegmentFault for Android 3.0 发布
  • Asm.js的简单介绍
  • Docker容器管理
  • extract-text-webpack-plugin用法
  • leetcode讲解--894. All Possible Full Binary Trees
  • node入门
  • Python语法速览与机器学习开发环境搭建
  • Spring Cloud Feign的两种使用姿势
  • 阿里云Kubernetes容器服务上体验Knative
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 警报:线上事故之CountDownLatch的威力
  • 思维导图—你不知道的JavaScript中卷
  • 我这样减少了26.5M Java内存!
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 关于Android全面屏虚拟导航栏的适配总结
  • ###C语言程序设计-----C语言学习(6)#
  • #define,static,const,三种常量的区别
  • #nginx配置案例
  • #QT(智能家居界面-界面切换)
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (3)STL算法之搜索
  • (39)STM32——FLASH闪存
  • (第二周)效能测试
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (转)使用VMware vSphere标准交换机设置网络连接
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .Net Redis的秒杀Dome和异步执行
  • .net/c# memcached 获取所有缓存键(keys)