设计模式之服务定位模式

发布于:2024-06-16 ⋅ 阅读:(18) ⋅ 点赞:(0)

服务定位器模式

服务定位器模式(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);
    }

    @Override
    public void init(String context) {
        //根据context 读取xml配置文件,初始化cache
        // 这里直接创建
        cache.put("userController",new UserController());
    }

    @Override
    public 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{
    @Override
    public 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);
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到