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

}

完美!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM