设计模式-策略模式升级(服务定位器模式)

设计模式-策略模式(服务定位器模式)

前言:

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

应用Service Locator Pattern

一、服务定位器

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

import org.springframework.stereotype.Component;

/**
 * @author dongliang7
 * @projectName
 * @ClassName PayParserFactory.java
 * @description: 支付服务定位器工厂接口
 * @createTime 2023年02月06日 15:01:00
 */
@Component
public interface PayParserFactory {
    /**
     * 服务定位器
     * @param payType 支付类型
     * @return 返回具体的支付处理实现类
     */
    PayService getPayParser(String payType);
}

二、配置ServiceLocatorFactoryBean

我们配置ServiceLocatorFactoryBean使用PayParserFactory作为服务定位器接口,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;

/**
 * @author dongliang7
 * @projectName
 * @ClassName PayParserConfig.java
 * @description: 支付解析器配置
 * @createTime 2023年02月06日 15:06:00
 */
@Configuration
public class PayParserConfig {

    /**
     * 初始化 payParserFactory bean
     * @return
     */
    @Bean("payParserFactory")
    public FactoryBean serviceLocatorFactoryBean() {
        ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
        // 设置服务定位接口
        factoryBean.setServiceLocatorInterface(PayParserFactory.class);
        return factoryBean;
    }
}

三、定义一个支付的接口

/**
 * @author dongliang7
 * @projectName
 * @ClassName PayParser.java
 * @description: 支付服务接口
 * @createTime 2023年02月06日 15:02:00
 */
public interface PayService {
    //支付接口
    boolean pay(String orderId);
}

四、根据不同类型处理Bean

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

  • 支付宝支付:
import org.springframework.stereotype.Component;

/**
 * @author dongliang7
 * @projectName
 * @ClassName AliPay.java
 * @description: 支付宝支付实现层
 * @createTime 2023年02月06日 15:09:00
 */
@Component("AliPay")
public class AliPayService implements PayService{
    @Override
    public boolean pay(String orderId) {
        System.out.println("支付宝支付-----------------------");
        return true;
    }
}
  • 微信支付:
import org.springframework.stereotype.Component;

/**
 * @author dongliang7
 * @projectName
 * @ClassName WxPayService.java
 * @description: 微信支付实现层
 * @createTime 2023年02月06日 15:17:00
 */
@Component("WxPay")
public class WxPayService implements PayService{
    @Override
    public boolean pay(String orderId) {
        System.out.println("微信支付-----------------------");
        return true;
    }
}

五、创建一个controller层

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author dongliang7
 * @projectName
 * @ClassName PayController.java
 * @description: 支付模块控制层
 * @createTime 2023年02月06日 15:20:00
 */
@RestController
@RequestMapping("/pay")
public class PayController {

    @Autowired
    private PayParserFactory payParserFactory;

    @PostMapping("/orderPay")
    public boolean orderPay(@RequestParam String payType) {
        // 关键点,直接根据类型获取
        boolean result = payParserFactory.getPayParser(payType).pay("P202302061524001");
        return result;
    }
}

总结:

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

 

posted @ 2023-02-06 16:08  AmourLee  阅读(204)  评论(0编辑  收藏  举报