• spring设计模式之applicationContext.getBean("beanName")思想


    1.背景

    在实际开发中我们会经常遇到不同的业务类型对应不同的业务处理,而这个业务类型又是经常变动的;

    比如说,我们在做支付业务的时候,可能刚开始需要实现支付宝支付和微信支付,那么代码逻辑可能如下

    /**
         * 支付选择简易逻辑
         *
         * @param payType payType zfb-支付宝支付,wx-微信支付
         * @param money   需要支付的钱
         */
        public void pay(String payType, Double money) {
            if ("zfb".equals(payType)) {
                System.out.println("=======执行支付宝支付========");
            } else if ("wx".equals(payType)) {
                System.out.println("=======执行支微信支付========");
            } else {
                System.out.println("=======支付类型错误========");
            }
        }

    咋一看,这样写也没有什么问题,但是如果因业务需要我们需要增加一个京东支付,那么我们又要else if ().....

    如果哪一天我们又要增加一个云闪付支付,那么我们又要else if ().....

    如果哪一天我们又要.....................

    这样的话,我们这个类会随着这支付类型的变动不断慢慢的扩展和修改....

    在修改的过程中甚至将原来的弄错......

    最后总结这样的代码违反了开闭原则,好的代码设计思想应该是对修改关闭,对扩展开放;

    那么应该如何写呢?

    大家可想想象一下,spring的getBean是怎么实现的,

    applicationContext.getBean("beanName");

    spring在设计的时候并不知道我们后来会写什么bean,它的内部不可能是通过名称 if else 来获取实例对象的,

    分析到这里大家有没有感觉到,这里的业务逻辑与我们的支付选择逻辑是相同的,

    既然这样,我们是不是可以看一看spring的getBean到是这样实现,如果能大体看懂,是不是我们也可以参照他的思想编写我们的支付逻辑.

    2.spring的getBean源码分析

    源码跟踪

     

     

     结论:看到最后,你会发现,spring的实例对象 是根据名称,以key,value的方式放在map中的;

    那么,我们的支付逻辑是不是也可以根据支付类型以key-value的方式存放;这样就不会再使用if else.

    3.支付业务逻辑实现

    1.订单实现类

      主要逻辑,

    a.在sping启动的时候,通过构造方法或去支付接口的所有实例

    b.遍历实例,将实例以key-value的方式放入map

    c.在具体支付的时候,通过支付类型从map中获取支付的具体实例,进行支付

    package com.example.demo.service.impl;
    
    import com.example.demo.service.IOrderService;
    import com.example.demo.service.IPayService;
    import org.springframework.stereotype.Service;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @Copyright (C) XXXXXXXX
     * @Author: 姿势帝
     * @Date: 2020-05-29 9:56
     * @Description:
     */
    @Service
    public class OrderServiceImpl implements IOrderService {
        /**
         * 存放支付类型的实例
         */
        private Map<String, IPayService> mapPay = new HashMap<>();
        /**
         * 构造方法
         * spring在实例化的时候会将所有的IPayServcie的实例放入list,在通过遍历放入map
         *
         * @param list
         */
        public OrderServiceImpl(List<IPayService> list) {
            for (IPayService iPayService : list) {
                mapPay.put(iPayService.getPayType(), iPayService);
            }
        }
        /**
         * @param payType zfb-支付宝支付,wx-微信支付,ysf-云闪付
         * @param money
         * @return
         */
        @Override
        public Object pay(String payType, Double money) {
            IPayService payService = mapPay.get(payType);
            if (payService == null) {
                System.out.println("没有对应的支付方式-->" + payType);
                return null;
            }
            payService.doPay(money);
            return null;
        }
    }

    支付接口

    package com.example.demo.service;
    
    /**
     * @Copyright (C) XXXXXXXX
     * @Author: 姿势帝
     * @Date: 2020-05-29 9:59
     * @Description:
     */
    public interface IPayService {
        /**
         * 获取支付类型
         * @return
         */
        String getPayType();
    
        /**
         * 具体支付
         * @param money
         * @return
         */
        Object doPay(Double money);
    }

    2.支付宝实现类

    package com.example.demo.service.impl;
    
    import com.example.demo.service.IPayService;
    import org.springframework.stereotype.Service;
    
    /**
     * @Copyright (C) XXXXXXXX
     * @Author: 姿势帝
     * @Date: 2020-05-29 10:01
     * @Description:
     */
    @Service
    public class PayAliPayServiceImpl implements IPayService {
        @Override
        public String getPayType() {
            return "zfb";
        }
    
        @Override
        public Object doPay(Double money) {
            System.out.println("======执行支付宝支付=======money="+money);
            return null;
        }
    }

    微信实现类

    package com.example.demo.service.impl;
    
    import com.example.demo.service.IPayService;
    import org.springframework.stereotype.Service;
    
    /**
     * @Copyright (C) XXXXXXXX
     * @Author: 姿势帝
     * @Date: 2020-05-29 10:01
     * @Description:
     */
    @Service
    public class PayWechatServiceImpl implements IPayService {
        @Override
        public String getPayType() {
            return "wx";
        }
    
        @Override
        public Object doPay(Double money) {
            System.out.println("======执行微信支付=======money="+money);
            return null;
        }
    }

    ....如果以后有京东,云闪付....等只需要写一个实现类即可,其他代码不需要做任何修改

    3.测试

    package com.example.demo;
    
    import com.example.demo.service.IOrderService;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.ApplicationContext;
    
    @SpringBootTest
    class DemoApplicationTests {
        @Autowired
        private ApplicationContext applicationContext;
    
        @Autowired
        private IOrderService orderService;
    
        /**
         * 测试支付
         * payType zfb-支付宝支付,wx-微信支付,其他支付....
         */
        @Test
        void testPay() {
            orderService.pay("zfb", 12.89);
        }
    
        /**
         * 获取bean的方法
         */
        @Test
        public void testBean() {
            applicationContext.getBean("beanName");
        }
    
    
        /**
         * 支付选择简易逻辑
         *
         * @param payType payType zfb-支付宝支付,wx-微信支付,其他支付....
         * @param money   需要支付的钱
         */
        public void pay(String payType, Double money) {
            if ("zfb".equals(payType)) {
                System.out.println("=======执行支付宝支付========");
            } else if ("wx".equals(payType)) {
                System.out.println("=======执行支微信支付========");
            } else {
                System.out.println("=======支付类型错误========");
            }
        }
    
    }

    完美!

  • 相关阅读:
    Instagram/IGListKit 实践谈(UICollectionView框架)
    谈UIView Animation编程艺术
    Swift Protobuf 初探 —— 继 XML 后,JSON 也要被淘汰了吗
    APP缓存数据线程安全问题
    玩转UICollectionViewLayout
    iOS常用宏 定义
    性能优化之NSDateFormatter
    iOS 用自签名证书实现 HTTPS 请求的原理
    iOS开发调试Reveal使用
    iOS配置SSO授权
  • 原文地址:https://www.cnblogs.com/newAndHui/p/12986449.html
Copyright © 2020-2023  润新知