什麼場景該使用通用計價 如果商品的費用屬性一直在變化,比如隔三岔五的新增某種費用(按新規則計算的新費用),作為開發人員的你每次需要膽戰心驚的維護現有的計價介面,測試也需要花費大量時間驗證對其他費用的影響。基於這一點,我在想如果初期把計價做成一個通用的計價介面,每次加費用我只需要關註新費用的計算規則, ...
什麼場景該使用通用計價
如果商品的費用屬性一直在變化,比如隔三岔五的新增某種費用(按新規則計算的新費用),作為開發人員的你每次需要膽戰心驚的維護現有的計價介面,測試也需要花費大量時間驗證對其他費用的影響。基於這一點,我在想如果初期把計價做成一個通用的計價介面,每次加費用我只需要關註新費用的計算規則,不需要去修改已有費用的規則計算代碼,也就可以避免一些BUG的產生。
簡單代碼實現
總體思路是利用Spring的容器管理,項目啟動時將所有計價類型載入在計價執行類中,具體調用方法和平時寫代碼一樣註入就行。這個方法並沒有在實際項目中使用。
1. 通用計價介面
import java.math.BigDecimal;
import java.util.Map;
public interface CommonValuation {
/**
* 計價類型
* @return
*/
String getValuationType();
/**
* 計價介面,子類實現自己的計價方式
* @param paramsJson
* @param result 保存所有的費用類型及金額
* @return
*/
void valuation(String paramsJson, Map<String, BigDecimal> result);
}
說明:這裡定義了計價介面,具體的計價類型和計算規則由子類實現,這裡會藉助Spring來管理子類。
2. 計價介面的執行類
@Component
public class CommonValuationChain {
@Autowired
private ApplicationContext applicationContext;
private List<CommonValuation> commonValuationList = new ArrayList<>();
/**
* 載入項目中所有的費用計算類
*/
@PostConstruct
private void init() {
String[] commonValuationArr = applicationContext.getBeanNamesForType(CommonValuation.class);
for (String cvName : commonValuationArr) {
commonValuationList.add(applicationContext.getBean(cvName, CommonValuation.class));
}
// 可以通過 @Order 決定計價的順序
AnnotationAwareOrderComparator.sort(commonValuationList);
}
public Map<String,BigDecimal> valuation(String paramsJson) {
// 保存所有的費用及對應的金額
Map<String,BigDecimal> result = new HashMap<>();
for(CommonValuation valuation : commonValuationList) {
valuation.valuation(paramsJson, result);
}
return result;
}
}
說明:這裡是藉助Spring的@PostConstruct註解,將所有的費用類型計算類載入到commonValuationList中,供業務方使用,子類也可以根據@Order註解決定計算的順序。
3. 具體費用類型
@Component
@Order(4)
public class DiscountMoneyValuation implements CommonValuation{
/**
* 減免費
* @return
*/
@Override
public String getValuationType() {
return "discountMoney";
}
@Override
public void valuation(String paramsJson, Map<String, BigDecimal> result) {
// 偽代碼,這裡可以將 paramsJson 轉換成需要的計價參數,計算真實價格
BigDecimal discountMoney = new BigDecimal("-10.6");
result.put(getValuationType(), discountMoney);
}
}
@Component
@Order(333)
public class TestMoneyValuation implements CommonValuation{
@Override
public String getValuationType() {
return "testMoney";
}
@Override
public void valuation(String paramsJson, Map<String, BigDecimal> result) {
// 偽代碼,這裡可以將 paramsJson 轉換成需要的計價參數,計算真實價格
BigDecimal testMoney = new BigDecimal("100");
result.put(getValuationType(), testMoney);
}
}
4. 調用類
@Autowired
private CommonValuationChain commonValuationCore;
@Test
public void valuationTest() {
Map<String,BigDecimal> result = commonValuationCore.valuation(null);
for(Map.Entry<String,BigDecimal> price : result.entrySet()) {
System.out.println(price.getKey() + ",金額" + price.getValue());
}
}
5. 執行結果
總結
以上是我個人對於通用計價的一種實現,本人水平有限,暫時想不到更有擴展性、可用性的方法,如果大家有更好的方法可以在下方評論,同時歡迎大家進行指導和批評。