【设计模式】服务定位器模式

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

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

实现

我们将创建 ServiceLocatorInitialContextCacheService 作为表示实体的各种对象。Service1 和 Service2 表示实体服务。

ServiceLocatorPatternDemo,我们的演示类在这里是作为一个客户端,将使用 ServiceLocator 来演示服务定位器设计模式。

步骤 1

创建服务接口 Service。

public interface Service {
   public String getName();
   public void execute();
}

步骤 2

创建实体服务。

public class Service1 implements Service {
   public void execute(){
      System.out.println("Executing Service1");
   }

   @Override
   public String getName() {
      return "Service1";
   }
}
public class Service2 implements Service {
   public void execute(){
      System.out.println("Executing Service2");
   }

   @Override
   public String getName() {
      return "Service2";
   }
}

步骤 3

为 JNDI 查询创建 InitialContext。

public class InitialContext {
   public Object lookup(String jndiName){
      if(jndiName.equalsIgnoreCase("SERVICE1")){
         System.out.println("Looking up and creating a new Service1 object");
         return new Service1();
      }else if (jndiName.equalsIgnoreCase("SERVICE2")){
         System.out.println("Looking up and creating a new Service2 object");
         return new Service2();
      }
      return null;
   }
}

步骤 4

创建缓存 Cache。

import java.util.ArrayList;
import java.util.List;

public class Cache {

   private List<Service> services;

   public Cache(){
      services = new ArrayList<Service>();
   }

   public Service getService(String serviceName){
      for (Service service : services) {
         if(service.getName().equalsIgnoreCase(serviceName)){
            System.out.println("Returning cached  "+serviceName+" object");
            return service;
         }
      }
      return null;
   }

   public void addService(Service newService){
      boolean exists = false;
      for (Service service : services) {
         if(service.getName().equalsIgnoreCase(newService.getName())){
            exists = true;
         }
      }
      if(!exists){
         services.add(newService);
      }
   }
}

步骤 5

创建服务定位器。

public class ServiceLocator {
   private static Cache cache;

   static {
      cache = new Cache();
   }

   public static Service getService(String jndiName){

      Service service = cache.getService(jndiName);

      if(service != null){
         return service;
      }

      InitialContext context = new InitialContext();
      Service service1 = (Service)context.lookup(jndiName);
      cache.addService(service1);
      return service1;
   }
}

步骤 6

使用 ServiceLocator 来演示服务定位器设计模式。

public class ServiceLocatorPatternDemo {
   public static void main(String[] args) {
      Service service = ServiceLocator.getService("Service1");
      service.execute();
      service = ServiceLocator.getService("Service2");
      service.execute();
      service = ServiceLocator.getService("Service1");
      service.execute();
      service = ServiceLocator.getService("Service2");
      service.execute();
   }
}

步骤 7

验证输出。

Looking up and creating a new Service1 object
Executing Service1
Looking up and creating a new Service2 object
Executing Service2
Returning cached  Service1 object
Executing Service1
Returning cached  Service2 object
Executing Service2
时间: 2025-01-15 07:46:38

【设计模式】服务定位器模式的相关文章

[翻译] 服务定位器是反模式

原文:Service Locator is an Anti-Pattern 服务定位器模式广为人知,Martin Fowler在文章中专门描述过它.所以它一定是好的,对不对? 并不是这样.服务定位器实际上是个反模式,应该避免使用.我们来研究一下.简单来讲,服务定位器隐藏了类之间的依赖关系,导致错误从编译时推迟到了运行时,并且,在引入破坏性更改时,这个模式导致代码不清晰,增加了维护难度. OrderProcessor 示例 我们用依赖注入话题中常见的OrderProcessor示例作说明.Orde

服务定位器【其他模式】

服务定位器 public class ServiceLocator extends Object { private static final String ZOOKEEPER_SERVICE = "zookeeperService"; private static final String JNDI_SERVICE = "jndiService"; /** * Service Locator Pattern[服务定位器模式] */ @Test public voi

GoF--服务定位器模式

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

Yii2设计模式——注册树模式

注册树模式 注册树模式(Registry Pattern)又叫注册模式.注册器模式.注册树模式通过将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘的模式设计方法. 为什么要采用注册树模式? 单例模式在整个项目中创建唯一实例的问题:工厂模式封装了对象的创建方式(工厂方法——用一个抽象方法,抽象工厂——用一簇抽象方法),使得不必总用new关键词去获取对象:创建者模式则是分步骤的创建实例的各个部分:在Yii2中则通过依赖注入容器DI去获取实例... 这些方法实际上都是解决一个问题——如何合

Lind.DDD.IoC(大叔推荐)~在服务定位器中引入IoC容器~容器的适配器

回到目录 关于依赖倒置(DIP) 高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口,通俗的讲,就是高层模块定义接口,低层模块负责实现,这在我们实际开发中经常被用到,层与层之间引用,经常被添加一个接口层去隔离,在接口层定义相关业务规范,而底层去实现它,高层只引用这个接口,当高级需要其它扩展,直接添加新的接口,由新的底层模块去实现即可,底层其它代码不需要修改,这也完全复合开闭原则(OCP). 关于控制反转(IOC) 控制反转是一种设计模式,像单例,工厂,适合器都属于设计模式的一种,

设计模式之代理模式 (三)

代理模式也叫委托模式. 一.定义: 代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象.这些额外的操作通常需要与实际对象进行通信. 二.角色定义 抽象角色:声明真实对象和代理对象的共同接口: 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象

Spring 实现两种设计模式:工厂模式和单态模式

在Spring 中大量使用的以下两种设计模式:工厂模式和单态模式. 工厂模式可将Java 对象的调用者从被调用者的实现逻辑中分离出来,调用者只需关心被调用者必须满足的规则(接口) ,而不必关心实例的具体实现过程.这是面向接口编程的优势,能提高程序的解耦,避免所有的类以硬编码方式耦合在一起. 如果所有的类直接耦合,极易形成"骨牌效应",假如B 类调用了A 类,一旦A 类需要修改,则B 类也需要修改:假如C 类调用了B 类,则C 类也需要修改......依次类推,从而导致整个系统都需要改写

C#设计模式(13)——代理模式(Proxy Pattern)

一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代理对象代替目标对象,然后客户端只需要访问代理对象,由代理对象去帮我们去请求目标对象并返回结果给客户端,这样的一个解决思路就是今天要介绍的代理模式. 二.代理模式的详细介绍 代理模式按照使用目的可以分为以下几种: 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象.这个不同的

java设计模式6——代理模式

java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代理 动态代理 1.3.代理模式关系图(以租房子为例) 2.静态代理 2.1.角色分析: 抽象角色:一般会使用接口或者抽象类来解决 真实角色:被代理的角色 代理客户:代理真实角色.代理真实角色后,我们一般会做一些附属的操作 客户:访问代理对象的人 2.2.例1(租房子演示) 2.2.1.抽象角色实现(