自定義註解(三)支付渠道:消除if-策略模式+工廠模式+單例模式
阿新 • • 發佈:2018-12-16
自定義支付註解=消除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、測試功能
驗證成功