策略模式+工厂模式 支付DEMO

 1-定义支付接口

/**
 * <简述>支付接口
 * <详细描述>
 * @author syf
 * @date 2023年07月26日 10:00
 */
public interface PayStrategy {
    //
    public void pay(double money);
}

2-定义支付宝 微信实现类 实现支付接口

/**
 * <简述>阿里支付
 * <详细描述>
 *
 * @author syf
 * @date 2023年07月26日 10:02
 */

@Service("ali")
public class AliPayStrategy implements PayStrategy {
    @Override
    public void pay(double money) {
        System.out.println(String.format("支付宝支付了:%.2f元", money));
    }
}
/**
 * <简述>微信支付
 * <详细描述>
 *
 * @author syf
 * @date 2023年07月26日 10:03
 */
@Service("wechat")
public class WeChatPayStrategy implements PayStrategy {
    @Override
    public void pay(double money) {
        System.out.println(String.format("微信支付了:%.2f元", money));
    }
}

3- 定义一个工厂来存储不同的策略对象

/**
 * <简述>定义一个工厂来存储不同的策略对象
 * <详细描述>
 * @author syf
 * @date 2023年07月26日 10:07
 */


@Component
public class PayStrategyFactory {



    //ConcurrentHashMap 现成安全的map
    private static Map<String, PayStrategy>  map = new ConcurrentHashMap<>();


    //静态代码块,在类加载的时候执行
    static {
        map.put("wechat", new WeChatPayStrategy());
        map.put("ali", new AliPayStrategy());
    }

    //通过类型找到策略对象
    public static PayStrategy getPayStrategy(String payType){
        return map.get(payType);
    }



}

4-测试接口

/**
 * <简述>
 * <详细描述>
 *
 * @author syf
 * @date 2023年07月26日 10:22
 */
@RestController
public class PayController {

    @Autowired
    private PayStrategyFactory payStrategyFactory;

    @GetMapping("/pay/{type}/{money}")
    public String pay(@PathVariable("type") String type, @PathVariable("money")double money){
        PayStrategy payStrategy = payStrategyFactory.getPayStrategy(type);
        if(null == payStrategy){
            return "支付类型为空" ;
        }
        payStrategy.pay(money);
        return "成功" ;
    }

}

结果展示

支付宝支付了:9999.00元

 5 - 延伸 (spring 管理bean)

工厂以及接口对象不应该自己new,最好交由spring管理

改造如下:PayStrategy 接口交由spring管理,实现工厂支付接口

5-1 枚举类
public enum PayTypes {
     wechat,ali
}
5-2 工厂类

根据枚举类型获取,支付接口的实例

枚举类

public enum PayTypes {
     WE_HCAT("wechat", "微信"),ALI("ali", "阿里");

     private String code;

     private String name;

     PayTypes(String code, String name) {
         this.code = code;
         this.name = name;
     }

     public String getCode() {
          return code;
     }

     /***
      * <简述>提供对外获取
      * <详细描述>
      * @author syf
      * @date 2023/8/14 10:40
      * @param code
      * @return com.ratelimiter.enums.PayTypes
      */
     public static PayTypes getEnum(String code){
          for(PayTypes animal:PayTypes.values()){
               if(animal.code.equals(code)){
                    return animal;
               }
          }
          return null;
     }
}

 支付实例的工厂类,PayStrategy 接口的实现类交由spring管理,放入map中存储

@Component
public class PayStrategyFactorySprings {


   
    /**
     * <简述>PayStrategy接口的实现类交给spring管理
     * <详细描述>@Autowired 注解来自动注入所有实现 PayStrategy 接口的 bean
        @Qualifier 根据bean名称注入
     * @return null
     * @author syf
     * @date 2023/8/2 23:30
     */
    @Autowired
    private PayStrategyFactoryNews(@Qualifier("ali") PayStrategy AliPayStrategy, @Qualifier("wechat") PayStrategy WeChatPayStrategy) {
       map.put(PayTypes.getEnum("ali").getCode(), AliPayStrategy);
       map.put(PayTypes.getEnum("wechat").getCode(), WeChatPayStrategy);
    }



    //提供对外的方法,可以通过key取到实现类
    public PayStrategy getPayStrategy(String type) {
        return map.get(type);
    }


}

上面是单个bean注入,也可以写成 用list注入 PayStrategy 接口的所有实现类

@Component
public class PayStrategyFactorySprings {

    @Autowired
    //使用注解注入,要注入的list泛型是接口而不是下边实现类,这样就会自动把次接口下的实现类都注入到list中
    private List<PayStrategy> payStrategyList;

    //创建hashMap来保存这些实现类,并且调用实现类的getType方法作为key,具体实现类为value(因为spring的BeanFactory时单例模式,所以不用担心会重复创建实现类,实际就是一个引用)
    //在外面就可以通过key来获取到对应的实现类,进行不同的动作
    private Map<String, PayStrategy> serviceMap = new HashMap<>();

    //在项目构建完成时,执行此方法 进行map的赋值
    @PostConstruct
    public void init() {
        //遍历实现类集合,根据循环到的实现类的getType()方法作为key,循环到的实现类zuoweuvalue,方便根据key取到对应实现类
        payStrategyList.stream().forEach(a -> {
            //@Service("ali")  @Service("wechat")
            serviceMap.put(a.getClass().getSimpleName() , a);
        });
    }

    //提供对外的方法,可以通过key取到实现类
    public PayStrategy getPayStrategy(String type) {
        return serviceMap.get(type);
    }

}

 如图

 

5-3调试接口
@RestController
@Slf4j
public class PayController {

   
     @Autowired
    private PayStrategyFactorySprings payStrategyFactorySprings;

    /**
     * <简述>工厂交由spring管理
     * <详细描述>
     * @author syf
     * @date 2023/7/26 15:22
     * @param type
     * @return java.lang.String
     */
     @GetMapping("/pay")
    public String pay(@RequestParam("type") String type){
        //获取接口工厂实例
        PayStrategy payStrategy = payStrategyFactorySprings.getPayStrategy(type);
        if(null == payStrategy){
            return "支付类型为空" ;
        }
        double money = 9999d;
        payStrategy.pay(money);
        return "成功" ;
    }

}

 

结果展示:

 

6- java后台多线程模拟测试接口

 引入单元测试类

    <!-- Junit 5 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

 编写测试类代码 测试接口

@SpringBootTest
public class Test {

    MockMvc mockMvc;
    @Autowired
    private WebApplicationContext wac;



    @org.junit.jupiter.api.Test
    public void pay() throws  Exception{
        this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        for (int i = 0; i < 10 ;i++){
            Thread thread = new Thread(() -> {
                try {
                    int type = new Random().nextInt(2);
                    double money = new Random().nextInt(100) + 1;

                    if (type == 0) {
                        mockMvc.perform(MockMvcRequestBuilders.get("/pay/wechat/" + money));
                    } else {
                        mockMvc.perform(MockMvcRequestBuilders.get("/pay/ali/" + money));
                    }

                } catch (Exception e) {

                }
            }, "用户1" + (i + 1) + "--->");

            thread.start();
        }
        Thread.sleep(5000);
    }
}

 用户12--->阿里将支付98.0
用户16--->阿里将支付3.0
用户17--->阿里将支付72.0
用户11--->阿里将支付13.0
用户110--->阿里将支付71.0
用户19--->阿里将支付53.0
用户18--->阿里将支付27.0
用户14--->阿里将支付10.0
用户15--->阿里将支付38.0
用户13--->阿里将支付51.0
用户16--->支付宝支付了:3.00元
用户18--->微信支付了:27.00元
用户14--->微信支付了:10.00元
用户15--->微信支付了:38.00元
用户17--->支付宝支付了:72.00元
用户13--->微信支付了:51.00元
用户11--->支付宝支付了:13.00元
用户19--->微信支付了:53.00元
用户110--->微信支付了:71.00元
用户12--->微信支付了:98.00元

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值