策略模式(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() |
分享到:
相关推荐
在Strategy模式中,我们将每种算法封装为一个策略类,每个策略类都实现了同一接口或抽象类,这样确保所有策略具有相同的契约。在上述案例中,我们可以创建一个`TaxStrategy`接口,包含计算税额的方法,然后为每个...
策略模式可以定义一系列的算法,并将每一个算法封装起来,让它们之间可以互相替换,让算法的变化独立于使用算法的客户。 策略模式的主要优点在于: 1. **灵活性**:当需要改变一种行为或算法时,我们无需修改原有...
Strategy模式封装算法。如果有多个算法可以互换使用,Strategy比较合适。 Bridge模式是对抽象和具体的进一步抽象。
在"策略模式封装的几个加密解密算法源码"中,我们主要关注的是如何使用策略模式来封装常见的加密解密算法,如BASE64和MD5。 1. **BASE64编码**:BASE64是一种用于将二进制数据编码为ASCII字符的编码方式,以便在...
策略模式可以定义一系列的算法,并将每一个算法封装起来,让它们之间可以互相替换,让算法的变化独立于使用它的客户。 核心概念: 1. **策略接口(Strategy Interface)**:定义了所有支持的算法的公共接口。客户端...
策略模式是软件设计中的一种行为模式,它允许在运行时选择算法或策略,提供了一种将算法封装在独立的可互换的类中的方式,使得程序在不修改原有代码的基础上,可以根据不同场景选择不同的算法实现。在“一个strategy...
Strategy模式允许我们在运行时选择不同的算法或行为。在RPG游戏中,我们可以定义一个策略接口`IWeaponBehavior`,包含`UseWeapon()`方法。然后,为每种武器类型(如剑、斧)创建一个具体策略类,实现`...
策略模式(Strategy Pattern)是一种行为型设计模式,旨在将算法封装成独立的类,并使它们可以互相替换。这种模式使得算法的变化独立于使用算法的客户端,从而提供了灵活性和可扩展性。策略模式常用于需要在运行时...
策略模式允许我们将这些算法封装成独立的类,每个类代表一种策略,然后在运行时动态选择要执行的策略。 策略模式的核心组成部分包括: 1. **策略接口(Strategy)**:定义了所有支持的算法或行为的公共接口。例如...
策略模式的核心思想是将一系列算法封装成一系列可以互换的类来组织起来,以便在程序中动态地选择合适的算法。 ##### 问题 在某些应用场景中,我们需要根据不同的条件或环境选择不同的算法来处理数据。例如,在实现...
Strategy模式提供了一种将算法族封装到各自独立的对象中,使得它们可以互换使用的方法。这样,我们可以避免硬编码特定的算法,而是让代码更加灵活,易于扩展。 在本范例中,我们将重点讨论如何应用Strategy模式来...
这种模式通常用于有多种算法可供选择的情况,根据不同的条件,可以选择不同的算法来完成任务,而这些算法的切换可以在运行时动态进行。 策略模式主要包含以下角色: 1. 环境(Context)角色:持有一个策略对象的引用...
在Java中,策略模式主要通过定义一系列的算法,并将每一个算法封装起来,使它们可以互相替换,让算法独立于使用它的客户而变化。这种模式的核心是策略接口和实现了策略接口的具体策略类。 策略模式的结构通常包括...
Java设计模式中的Strategy模式是一种对象行为型模式,其主要目的是定义一系列算法,并将这些算法封装成独立的类,使得它们可以互相替换,让算法的变化独立于使用算法的客户。在Strategy模式中,核心思想是封装可能...
这种模式的核心思想是定义一系列算法,并将每一个算法封装起来,使它们可以相互替换,让算法的变化独立于使用算法的客户。在C++中实现Strategy模式,我们可以充分利用面向对象的特性,如多态性,来达到灵活地切换...
总结来说,策略模式在Java和Android开发中是一种非常实用的设计模式,它通过封装不同的策略,使程序能够根据需要在运行时灵活选择和切换算法,提高了代码的灵活性和可扩展性。理解和掌握策略模式对于提升Android开发...
该模式定义了一系列算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化独立于使用算法的客户。 在C#中实现策略模式,首先需要定义一个策略接口,该接口声明了所有具体策略所共有的方法...
策略模式提供了一种将算法族封装到各自独立的类中,并让它们之间可以互相替换的方法。这样,算法的变化就不会影响到使用算法的客户端代码,使得系统更加灵活且易于维护。 策略模式的核心组成部分包括环境(Context)...
Strategy模式的核心思想是定义一系列算法,并将每一个算法封装起来,使它们可以相互替换。这样做的好处是算法的变化不会影响到使用算法的客户。在面向对象编程中,Strategy模式通常通过接口或抽象类来定义这些算法的...
通过将算法封装到具有共同接口的独立对象中,策略模式使得你可以根据需要灵活地切换算法,或者在运行时添加新的算法。 在策略模式中,主要有三个关键角色: 1. **策略(Strategy)接口**:定义了所有支持的算法的...