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("=======支付類型錯誤========"); } } }
完美!