java设计模式之策略模式应用:订单手续费计算

本文介绍了如何使用Java设计模式中的策略模式来处理订单手续费计算问题。根据商户类型和交易金额,手续费计算规则包括固定费用、百分比费用、分段固定费用和分段百分比费用。通过策略接口和多个实现类,实现了手续费计算的灵活性和可扩展性。
摘要由CSDN通过智能技术生成
  • 首先在阐述需求之前对一些名词做点解释:
  1. 商户编号:有使用过POS机刷卡的同学,可能都会注意到POS签购单上有一个商户编号,这个编号有15位,前三位代表收单银行,第四位到第七位代表行政区划代码,第八位到第十一位代表商户类型代码及MCC码,最后四位就没什么特殊的了。
  2. 手续费:每一笔订单都会产生一笔手续费,从结算给商户的金额中扣取,和刷卡的客户无太多关系,一般按发卡行:收单机构:银联的比例为7:3:1或者8:1:1进行清分。
  3. 扣率:费率根据商户的类型(MCC)不同而不同,现在民生类的是0.38%的手续费,一般类是0.78%,餐娱类是1.25%。
  4. 订单:订单就是订单啦,应该没人不理解啦。
  • 然后描述需求:

现在针对每一笔订单,都会关联到一个商户;每一个商户关联一个固定商户编号;每个商户编号有不同的扣率。比如: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;
	}
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值