策略模式(Strategy)说穿了就是通过对接口的定义,将应用中变化的部分独立出来由子类实现,从而实现松耦合。
问题的起源来自银监会项目的需求变化,“本次应缴金额”的计算公式有变动。公式计算规则如下:
|
二、“本次应缴金额”自动运算公式
收缴系统的[收入收缴管理]-[监管收费]-[应缴信息录入]中“本次应缴金额”的自动计算公式需改为:
(一)每年第1期“本次应缴金额”
机构监管费=(上年末实收资本×机构监管费率×风险调整系数)÷2
业务监管费=[(上年末资产总额-实收资本)×业务监管费率×风险调整系数-境外分支机构在所在国家缴纳的监管费]÷2
(二)每年第2期“本次应缴金额”
机构监管费=全年应缴机构监管费-第1次应缴机构监管费=上年末实收资本×机构监管费率×风险调整系数-第1次应缴机构监管费
业务监管费=全年应缴业务监管费-第1次应缴业务监管费=[(上年末资产总额-实收资本)×业务监管费率×风险调整系数-境外分支机构在所在国家缴纳的监管费]-第1次应缴业务监管费
请你公司协助完成收缴系统的修改和调试工作。
|
拿到需求时单是看到琳琅满目的数据字段我就已经头晕了。。,再看看手中原有的代码,计算公式全是在actionPerform()一个方法内完成的,我如果在原有基础上修改,势必会使用大量if else,绕啊绕,换个人也会头晕。“只在此山中,云深不知处”的意境虽然美,但是不适用在代码中。于是我想到了策略模式。
通过观察,公式需要计算
1. 每年需要计算两期:第一期和第二期(废话:P);
2. 每期需要计算两种不同的费用:机构监管费和业务监管费;
于是我定义出接口:
|
publicinterface ICountStrategy {
/**
*计算机构监管费
*/
public UFDouble countCorpfee();
/**
*计算业务监管费
*/
public UFDouble countBusifee();
}
|
|
publicclass CalStrategyObject {
private UFDouble receivedfund = null; // 上年末实收资本
private UFDouble totalfund = null; // 上年末总资产
private UFDouble riskvalue = null;// 风险调整系数
private UFDouble corprate = null;// 机构监管费率
private UFDouble busirate = null;// 业务监管费率
private UFDouble outerfund = null;// 境外分支机构在所在国家缴纳的监管费
private UFDouble corpfund1 = null;// 第1次应缴机构监管费
private UFDouble busifund1 = null;// 第一次应缴业务监管费
//setter getter方法
}
|
为了节省篇幅,Setter Getter方法我就不写了。通过这个类,其他程序员就知道,原来参与计算的就是这些数据啊!
|
publicabstractclass AbstractCountStrategy implements ICountStrategy {
privatebooleanisRefresh = false;
protected CalStrategyObject calobj = null;
/**
*@paramcalobj用于计算的数据vo
*/
public AbstractCountStrategy(CalStrategyObject calobj) {
this.calobj = calobj;
}
publicvoid setCalStrategyObj(CalStrategyObject calobj) {
this.calobj = calobj;
}
}
|
下一步,开始真正实现每期不同费用的算法了。
|
/**
*第一期的计算公式
*
*@authorwuz
*
*/
publicclass FirstTermCalculator extends AbstractCountStrategy {
public FirstTermCalculator(CalStrategyObject calobj) {
super(calobj);
}
/*
* 业务监管费=[(上年末资产总额-实收资本)¡Á业务监管费率¡Á风险调整系数-境外分支机构在所在国家缴纳的监管费]¡Â2;
*/
public UFDouble countBusifee() {
UFDouble totalBusifee = CalculatorUtil.countTotalBusiFee(calobj);
return totalBusifee.div(2);
}
/*
* 每年第1期“本次应缴金额” 机构监管费=(上年末实收资本¡Á机构监管费率¡Á风险调整系数)¡Â2
*/
public UFDouble countCorpfee() {
UFDouble totalFee = CalculatorUtil.countTotalCorpFee(calobj);
return totalFee.div(2);
}
}
|
|
publicclass SecondTermCalculator extends AbstractCountStrategy {
public SecondTermCalculator(CalStrategyObject calobj) {
super(calobj);
}
/*
* 业务监管费=全年应缴业务监管费-第1次应缴业务监管费=[(上年末资产总额-实收资本)¡Á业务监管费率¡Á风险调整系数-境外分支机构在所在国家缴纳的监管费]-第1次应缴业务监管费
*/
public UFDouble countBusifee() {
UFDouble busifee1 = calobj.getBusifund1();// 第1次应缴业务监管费
UFDouble totalfee = CalculatorUtil.countTotalBusiFee(calobj);// 全年应缴业务监管费
return totalfee.sub(busifee1);
}
/*
* 机构监管费=全年应缴机构监管费-第1次应缴机构监管费=上年末实收资本¡Á机构监管费率¡Á风险调整系数-第1次应缴机构监管费
*/
public UFDouble countCorpfee() {
UFDouble corpfee = CalculatorUtil.countTotalCorpFee(calobj);
UFDouble orgfee1 = calobj.getCorpfund1();// 第1次应缴机构监管费
return corpfee.sub(orgfee1);
}
}
|
这里由于公式中,“(上年末实收资本×机构监管费率×风险调整系数)”和“(上年末资产总额-实收资本)×业务监管费率×风险调整系数-境外分支机构在所在国家缴纳的监管费 ”两个公式多次用到,我将其提炼到一个工具类CalculatorUtil中:
|
publicclass CalculatorUtil {
/**
*计算总的机构监管费上年末实收资本¡Á机构监管费率¡Á风险调整系数
*
*@paramcalobj
*@return
*/
publicstatic UFDouble countTotalCorpFee(CalStrategyObject calobj) {
UFDouble receivedFund = calobj.getReceivedfund();
UFDouble riskvalue = calobj.getRiskvalue();
UFDouble rate = calobj.getCorprate();
return receivedFund.multiply(rate).multiply(riskvalue);
}
/**
*业务监管费总额(上年末资产总额-实收资本)¡Á业务监管费率¡Á风险调整系数-境外分支机构在所在国家缴纳的监管费
*业务监管费率是一个范围值,不同范围取值不一样
*
*
*@paramcalobj
*@return
*@throwsException
*/
publicstatic UFDouble countTotalBusiFee(CalStrategyObject calobj){
UFDouble total = calobj.getTotalfund();// 上年末资产总额
UFDouble receivedFund = calobj.getReceivedfund();// 实收资本
UFDouble sub = total.sub(receivedFund);//按照(上年末资产总额-实收资本)计算业务监管费
UFDouble business = BusiRateUtil.getInstance().getBusiFee(sub);
UFDouble riskrate = calobj.getRiskvalue();// 风险调整系数
UFDouble outfee = calobj.getOuterfund();// 境外分支机构在所在国家缴纳的监管费
return business.multiply(riskrate).sub(outfee);
}
}
|
|
publicclass CalculatorFactory {
/**
*@paramtype期次
*@return
*/
public ICountStrategy createCalculator(int type){
if(type ==1 ){
returnnew FirstTermCalculator();
}else {
returnnew SecondTermCalculator();
}
returnnull;
}
}
|
|
publicclass PayableCalculator {
...
privatevoid onCount1() throws Exception {
CalStrategyObject obj = getCalobj();
ICountStrategy counter = new FirstTermCalculator(obj);
UFDouble orgFee = counter.countCorpfee();
data.setOrgfee(orgFee);
UFDouble busifee = counter.countBusifee();
data.setBusifee(busifee);
}
...
privatevoid onCount2() |
面对银监会项目中“本次应缴金额”计算公式的变动需求,本文通过策略模式实现了灵活应对。策略模式通过定义接口将变化部分独立出来,以适应不同期次和费用类型的计算。文中详细介绍了策略模式的设计与实现过程。
553

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



