- 首先在阐述需求之前对一些名词做点解释:
- 商户编号:有使用过POS机刷卡的同学,可能都会注意到POS签购单上有一个商户编号,这个编号有15位,前三位代表收单银行,第四位到第七位代表行政区划代码,第八位到第十一位代表商户类型代码及MCC码,最后四位就没什么特殊的了。
- 手续费:每一笔订单都会产生一笔手续费,从结算给商户的金额中扣取,和刷卡的客户无太多关系,一般按发卡行:收单机构:银联的比例为7:3:1或者8:1:1进行清分。
- 扣率:费率根据商户的类型(MCC)不同而不同,现在民生类的是0.38%的手续费,一般类是0.78%,餐娱类是1.25%。
- 订单:订单就是订单啦,应该没人不理解啦。
- 然后描述需求:
现在针对每一笔订单,都会关联到一个商户;每一个商户关联一个固定商户编号;每个商户编号有不同的扣率。比如:1、按每笔收取固定手续费,没交易一笔订 单,收取5角;2、按百分比收取手续费,比如民生类商户按0.38%收取手续费,封顶金额16元;3、按不同交易金额区间收取不同的手续费,比如 0~5000收取每笔订单1元,5000~50000收取每笔订单5角,大于50000收取每笔订单2角;4、不同交易金额区间按不同百分比收取手续费等 等。
- 具体设计不做赘述,直接上类图:

策略接口StrategyCharge定义了一个计算手续费的方法,有四个实现类StrategyWithCount、StrategyWithCountByStage、StrategyWithRatio和StrategyWithRatioByStage,顾名思义,这四个类分别负责计算1每笔收取固定手续费、2每笔按不同金额区间收取不同手续费、3每笔按固定百分比收取手续费和4每笔按不同金额区间根据不同百分比收取手续的计算。
- 所有类的代码如下:
package src.designpattern.strategy.ex2.model;
/**
* 扣率实体
*
* @author wusj
* @time 2015年8月10日 上午11:23:06
*/
public class DeductionRate {
private String id;
/**
* 资金范围开始值
*/
private String rangeBottom;
/**
* 资金范围结束值
*/
private String rangeTop;
/**
* 扣率,(0,1)之间表示百分比,大于等于1表示每交易扣款金额(单位为分)
*/
private String ratio;
/**
* 最大值
*/
private String maximum;
/**
* 最小值
*/
private String minimum;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getRangeBottom() {
return rangeBottom;
}
public void setRangeBottom(String rangeBottom) {
this.rangeBottom = rangeBottom;
}
public String getRangeTop() {
return rangeTop;
}
public void setRangeTop(String rangeTop) {
this.rangeTop = rangeTop;
}
public String getRatio() {
return ratio;
}
public void setRatio(String ratio) {
this.ratio = ratio;
}
public String getMaximum() {
return maximum;
}
public void setMaximum(String maximum) {
this.maximum = maximum;
}
public String getMinimum() {
return minimum;
}
public void setMinimum(String minimum) {
this.minimum = minimum;
}
}
package src.designpattern.strategy.ex2.model;
/**
* 扣率和商户编码关联关系
*
* @author wusj
* @date 2015年8月10日 上午11:38:34
*/
public class DeRateRelateMerCode {
private String id;
/**
* 扣率ID
*/
private String decutionRateId;
/**
* 商户编号ID
*/
private String merchantCodeId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDecutionRateId() {
return decutionRateId;
}
public void setDecutionRateId(String decutionRateId) {
this.decutionRateId = decutionRateId;
}
public String getMerchantCodeId() {
return merchantCodeId;
}
public void setMerchantCodeId(String merchantCodeId) {
this.merchantCodeId = merchantCodeId;
}
}
package src.designpattern.strategy.ex2.model;
/**
* 商户号实体
*
* @author wusj
* @time 2015年8月10日 上午11:23:20
*/
public class MerchantCode {
private String id;
private String merchantName;
/**
* 扣率类型:
* 1每笔收取固定手续费;
* 2每笔按不同金额区间收取不同手续费;
* 3每笔按固定百分比收取手续费;
* 4每笔按不同金额区间根据不同百分比收取手续。
*/
private String rateType;
/**
* 手续费计算类
*/
private String chargeCalClass;
private String others;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMerchantName() {
return merchantName;
}
public void setMerchantName(String merchantName) {
this.merchantName = merchantName;
}
public String getRateType() {
return rateType;
}
public void setRateType(String rateType) {
this.rateType = rateType;
}
public String getChargeCalClass() {
return chargeCalClass;
}
public void setChargeCalClass(String chargeCalClass) {
this.chargeCalClass = chargeCalClass;
}
public String getOthers() {
return others;
}
public void setOthers(String others) {
this.others = others;
}
}
package src.designpattern.strategy.ex2.model;
/**
* 订单实体
*
* @author wusj
* @date 2015年8月10日 上午11:54:43
*/
public class Order {
private String id;
/**
* 交易金额(单位分)
*/
private String amount;
/**
* 商户编号ID
*/
private String merchantCodeId;
/**
* 手续费(单位分)
*/
private String charge;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getMerchantCodeId() {
return merchantCodeId;
}
public void setMerchantCodeId(String merchantCodeId) {
this.merchantCodeId = merchantCodeId;
}
public String getCharge() {
return charge;
}
public void setCharge(String charge) {
this.charge = charge;
}
}
package src.designpattern.strategy.ex2.service;
import src.designpattern.strategy.ex2.model.Order;
/**
* 订单接口
*
* @author wusj
* @date 2015年8月10日 上午11:57:21
*/
public interface OrderService {
Order insert(Order order);
void update(Order order);
void delete(String orderId);
void query(String orderId);
}
package src.designpattern.strategy.ex2.service;
/**
* 策略接口定义
*
* @author wusj
* @date 2015年8月10日 上午11:59:55
*/
public interface StrategyCharge {
/**
* 计算手续费
*
* @param object
* @return 返回手续费的字符串形式,单位为分
*/
String calcullateCharge(Object object);
}
package src.designpattern.strategy.ex2;
import src.designpattern.strategy.ex2.service.StrategyCharge;
/**
*
*
* @author wusj
* @date 2015年8月10日 上午11:59:24
*/
public class ContextCharge {
protected StrategyCharge strategyCharge;
public String calculateCharge(Object object) {
return strategyCharge.calcullateCharge(object);
}
}
package src.designpattern.strategy.ex2;
import src.designpattern.strategy.ex2.model.Order;
import src.designpattern.strategy.ex2.service.OrderService;
import src.designpattern.strategy.ex2.service.StrategyCharge;
/**
* 订单接口实现类
*
* @author wusj
* @date 2015年8月10日 下午1:19:32
*/
public class OrderServiceImpl extends ContextCharge implements OrderService {
public OrderServiceImpl(StrategyCharge strategyCharge) {
this.strategyCharge = strategyCharge;
}
public Order insert(Order order) {
String charge = this.calculateCharge(order);
order.setCharge(charge);
System.out.println("insert data");
return order;
}
public void update(Order order) {
System.out.println("update data.");
}
public void delete(String orderId) {
System.out.println("delete data.");
}
public void query(String orderId) {
System.out.println("query data.");
}
}
package src.designpattern.strategy.ex2;
import java.util.ArrayList;
import java.util.List;
import src.designpattern.strategy.ex2.model.DeductionRate;
import src.designpattern.strategy.ex2.model.Order;
import src.designpattern.strategy.ex2.service.StrategyCharge;
/**
* 计算每笔收取固定金额手续费的算法
*
* @author wusj
* @date 2015年8月10日 下午12:38:48
*/
public class StrategyWithCount implements StrategyCharge {
public String calcullateCharge(Object object) {
// 计算订单的手续费,如果不是订单,抛出异常
if (object instanceof Order) {
Order order = (Order) object;
String merchantCodeId = order.getMerchantCodeId();
// 根据merchantCodeId查询DeRateRelateMerCode,再查询DeductionRate
List<DeductionRate> rateList = query(merchantCodeId);
DeductionRate rate = rateList.get(0);
return rate.getRatio();
} else {
throw new UnsupportedOperationException();
}
}
/**
* 模拟查询
*
* @param merchantCodeId
* @return
*/
private List<DeductionRate> query(String merchantCodeId) {
// 需要实现
DeductionRate rate = new DeductionRate();
rate.setId("123");
// 模拟每笔收取0.5元(即50fen)的手续费
rate.setRatio("50");
List<DeductionRate> list = new ArrayList<DeductionRate>(1);
list.add(rate);
return list;
}
}
package src.designpattern.strategy.ex2;
import src.designpattern.strategy.ex2.model.Order;
import src.designpattern.strategy.ex2.service.StrategyCharge;
/**
* 每笔按不同金额区间收取不同手续费的算法
*
* @author wusj
* @date 2015年8月10日 下午12:38:48
*/
public class StrategyWithCountByStage implements StrategyCharge {
public String calcullateCharge(Object object) {
// 计算订单的手续费,如果不是订单,抛出异常
if (object instanceof Order) {
// 算法
return "";
} else {
throw new UnsupportedOperationException();
}
}
}
package src.designpattern.strategy.ex2;
import java.util.ArrayList;
import java.util.List;
import src.designpattern.strategy.ex2.model.DeductionRate;
import src.designpattern.strategy.ex2.model.Order;
import src.designpattern.strategy.ex2.service.StrategyCharge;
/**
* 计算每笔收取“交易金额*固定百分比”的手续费算法
*
* @author wusj
* @date 2015年8月10日 下午12:38:48
*/
public class StrategyWithRatio implements StrategyCharge {
public String calcullateCharge(Object object) {
// 计算订单的手续费,如果不是订单,抛出异常
if (object instanceof Order) {
Order order = (Order) object;
String merchantCodeId = order.getMerchantCodeId();
// 根据merchantCodeId查询DeRateRelateMerCode,再查询DeductionRate
List<DeductionRate> rateList = query(merchantCodeId);
DeductionRate rate = rateList.get(0);
String ratio = rate.getRatio();
String maximum = rate.getMaximum();
String minimum = rate.getMinimum();
Float ratioF = Float.parseFloat(ratio);
Float maximumF = (maximum == null || "".equals(maximum)) ? -1f
: Float.parseFloat(maximum);
Float minimumF = (minimum == null || "".equals(minimum)) ? 0f
: Float.parseFloat(minimum);
Float amountF = Float.parseFloat(order.getAmount());
Float chargeF = amountF * ratioF;
chargeF = chargeF < minimumF ? minimumF : chargeF;
chargeF = (maximumF != -1f && chargeF > maximumF) ? maximumF
: chargeF;
return String.valueOf(Math.round(chargeF));
} else {
throw new UnsupportedOperationException();
}
}
/**
* 模拟查询
*
* @param merchantCodeId
* @return
*/
private List<DeductionRate> query(String merchantCodeId) {
// 需要实现
DeductionRate rate = new DeductionRate();
rate.setId("123");
// 模拟每笔手续交易金额*0.005,封顶手续费10元(1000分)
rate.setRatio("0.005");
rate.setMaximum("1000");
List<DeductionRate> list = new ArrayList<DeductionRate>(1);
list.add(rate);
return list;
}
}
package src.designpattern.strategy.ex2;
import src.designpattern.strategy.ex2.model.Order;
import src.designpattern.strategy.ex2.service.StrategyCharge;
/**
* 每笔按不同金额区间根据不同百分比收取手续
*
* @author wusj
* @date 2015年8月10日 下午12:38:48
*/
public class StrategyWithRatioByStage implements StrategyCharge {
public String calcullateCharge(Object object) {
// 计算订单的手续费,如果不是订单,抛出异常
if (object instanceof Order) {
// 算法
return "";
} else {
throw new UnsupportedOperationException();
}
}
}
package src.designpattern.strategy.ex2;
import src.designpattern.strategy.ex2.model.MerchantCode;
import src.designpattern.strategy.ex2.model.Order;
import src.designpattern.strategy.ex2.service.OrderService;
import src.designpattern.strategy.ex2.service.StrategyCharge;
/**
* 测试类
*
* @author wusj
* @date 2015年8月10日 下午1:24:23
*/
public class MainTest {
public static void main(String[] args) {
String merchantCodeId = "159";
Order order = new Order();
order.setAmount("100");
order.setId("123");
order.setMerchantCodeId(merchantCodeId);
try {
OrderService orderService = new OrderServiceImpl(
getContextCharge(merchantCodeId));
Order temp = orderService.insert(order);
System.out.println(temp.getCharge());
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("rawtypes")
static StrategyCharge getContextCharge(String merchantCodeId)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
MerchantCode code = getMerchantCode(merchantCodeId);
String className = code.getChargeCalClass();
Class clazz = Class.forName(className);
StrategyCharge charge = (StrategyCharge) clazz.newInstance();
return charge;
}
static MerchantCode getMerchantCode(String merchantCodeId) {
MerchantCode code = new MerchantCode();
code.setId(merchantCodeId);
code.setMerchantName("wusj");
code.setRateType("1");
// 测试每笔固定金额
// code.setChargeCalClass("src.designpattern.strategy.ex2.StrategyWithCount");
// 测试每笔固定比例,且最多可收取的手续费限额
code.setChargeCalClass("src.designpattern.strategy.ex2.StrategyWithRatio");
code.setOthers("others");
return code;
}
}

本文介绍了如何使用Java设计模式中的策略模式来处理订单手续费计算问题。根据商户类型和交易金额,手续费计算规则包括固定费用、百分比费用、分段固定费用和分段百分比费用。通过策略接口和多个实现类,实现了手续费计算的灵活性和可扩展性。

1584

被折叠的 条评论
为什么被折叠?



