1. 程式人生 > >自定義註解(三)支付渠道:消除if-策略模式+工廠模式+單例模式

自定義註解(三)支付渠道:消除if-策略模式+工廠模式+單例模式

自定義支付註解=消除if:策略模式+工廠模式+單例模式

程式碼取景,知識來源於視訊《雲析學院【路飛老師】-一次學習終身受用-如何正確使用設計模式寫出優雅的程式碼》

1、定義註解標籤 PayChannel

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PayChannel {
    int channelId();
}

2、建立支付渠道策略介面及其不同實現類

1)定義價格介面PayStrategy

public interface PayStrategy {
/** * 根據渠道計算價格 * @param channelId * @param goodsId * @return */ BigDecimal calRecharge(Integer channelId,Integer goodsId); }

2)建立不同的價格介面實現類, 包名:com.yf.custom.pay.impl

工商銀行

@PayChannel(channelId = 1)
public class ICBCBank implements PayStrategy{
    @Override
    public
BigDecimal calRecharge(Integer channelId, Integer goodsId) { return new BigDecimal("1"); } }

招商銀行

@PayChannel(channelId = 2)
public class CMBCBank implements PayStrategy{
    @Override
    public BigDecimal calRecharge(Integer channelId, Integer goodsId) {
        return new BigDecimal
("2"); } }

有需要的話繼續擴充套件,建立實現類即可

3、建立工廠類

1)單例模式獲取 PayStrategyFactory例項; 2)掃描指定實現類,儲存所有的payChannel資訊;

ps:Reflections依賴maven如下:

<!-- 操作反射 -->
		<dependency>
			<groupId>org.reflections</groupId>
			<artifactId>reflections</artifactId>
			<version>0.9.10</version>
		</dependency>

3)根據類名呼叫對應實現類方法,見create(String channelId)

public class PayStrategyFactory {
    //餓漢式 單例模式
    private static PayStrategyFactory payStrategyFactory=new PayStrategyFactory();

    /**
     * 單例模式-私有構造器
     */
    private PayStrategyFactory(){

    }
    public static PayStrategyFactory getInstance(){
        return payStrategyFactory;
    }

    /**
     * 重點:儲存所有的payChannel
     */
    public static HashMap<Integer,String> payChannelMap=new HashMap<>();

    static {
        //1、掃描支付渠道的實現類 ,Reflections 依賴 Google 的 Guava 庫和 Javassist 庫
        Reflections reflections = new Reflections("com.yf.custom.pay.impl");
        //2、獲取所有包含PayChannel註解的類
        Set<Class<?>> classList = reflections.getTypesAnnotatedWith(PayChannel.class);
        for (Class clazz : classList) {
            PayChannel t = (PayChannel) clazz.getAnnotation(PayChannel.class);
            //3、賦值payChannelMap,儲存所有的支付渠道
            payChannelMap.put(t.channelId(), clazz.getCanonicalName());
        }

    }
    /**
     *  根據channelId獲取對應的具體實現
     * @param channelId
     * @return
     */
    public PayStrategy create(Integer channelId) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //1.獲取渠道對應的類名
        String clazz=payChannelMap.get(channelId);
        Class clazz_=Class.forName(clazz);
        /**
         * newInstance :工廠模式經常使用newInstance來建立物件,newInstance()是實現IOC、反射、依賴倒置 等技術方法的必然選擇
         *      呼叫class的載入方法載入某個類,然後例項化
         *
         * new 只能實現具體類的例項化,不適合於介面程式設計
         */
        return (PayStrategy) clazz_.newInstance();
    }
}

4、測試功能

驗證成功