开闭原则spring中的解决方式

需求:

  • 完成支付模块需要支持微信支付,支付宝支付,通过传入code区分不同的支付方式,完成不同的支付逻辑
  • 我们首先想到的是用if 判断支付方式 :
if(payType.getCode == 101){
	// 支付宝支付
} else if(payType.getCode == 102){
	// 微信支付逻辑
}

但是如果我们需要增加一个银联支付,则需要继续改动业务逻辑,添加更多的if else,这样明显不符合设计原则中的开闭原则:对扩展开放,对修改关闭

所以产生了如下的解决方式:

  • PayCode.java 支付方式自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PayCode {
    int value();
    String name();
}
  • Pay.java 支付接口
public interface Pay {
    /**
     * pay
     */
    void pay();
}
  • AliPay.java 支付宝支付业务逻辑
@PayCode(value = 101, name = "支付宝")
public class AliPay implements Pay{
    @Override
    public void pay() {
        System.out.println("执行支付宝支付逻辑...");
    }
}
  • WechatPay.java 微信支付业务逻辑
@PayCode(value = 102, name = "微信")
public class WechatPay implements Pay{
    @Override
    public void pay() {
        System.out.println("执行微信支付逻辑...");
    }
}
  • PayEnum 支付方式枚举类
@Getter
public enum PayEnum {
    ALI_PAY(101,"支付宝支付"),
    WECHAT_PAY(102, "微信支付");
    private Integer code;
    private String msg;
    PayEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}
  • PayConfiguration.java 让Spring扫描到注解标记的类
@Configuration
@ComponentScan(includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = PayCode.class)
})
public class PayConfiguration {
}
  • TestService.java 监听器,从spring容器得到被PayCode注解标记类的对象,并通过传入的code调用调用不同的pay方法
@Service
public class TestService implements ApplicationListener<ContextRefreshedEvent> {
    private Map<Integer, Pay> payMap = null;
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class);
        payMap = new ConcurrentHashMap<>();
        beansWithAnnotation.forEach((key, value) -> {
            Integer type = value.getClass().getAnnotation(PayCode.class).value();
            payMap.put(type, (Pay) value);
        });
    }
    public void pay(PayEnum payEnum) {
        payMap.get(payEnum.getCode()).pay();
    }
}
  • DemoTest.java 测试类
public class DemoTest {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(PayConfiguration.class);
        TestService testService = context.getBean("testService", TestService.class);
        testService.pay(PayEnum.ALI_PAY);
        testService.pay(PayEnum.WECHAT_PAY);
    }
}

  • 结果
执行支付宝支付逻辑...
执行微信支付逻辑...
  • 这样,我们即便在将来的业务中需要添加银联支付,也不需要改动原有代码,新增一个银联支付的类即可
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值