Mat*_*tyf 12 java oop algorithm design-patterns
我面临一个编程问题,我不知道如何以面向对象和灵活的方式解决.我想到了一些糟糕的解决方案,但我正在寻找一个好的解决方案.我用Java开发,所以我更喜欢Java思想,但任何面向对象的想法都是受欢迎的.
我一直在寻找可以帮助我的想法,设计模式或一些算法,但我不知道哪个术语或名称给我的问题,所以我找不到任何线索.
问题:
摘要:
我需要跟踪对一组实体进行不同更改的过程的部分结果.我需要这个向用户报告表格报告中每个计算"步骤"的详细信息.而且我还需要将此集合保存在数据库中.
详情:
我维护的软件有一个类似于这个的实体:
public class Salary {
private Date date;
private BigDecimal amount;
}
Run Code Online (Sandbox Code Playgroud)
这是一个集合,如下所示:
List<Salary> thisYearSalaries;
Run Code Online (Sandbox Code Playgroud)
这组实体可以通过一组"任务"修改,具体取决于一些规则:
例如:
public void processSalaries(List<Salary> theSalaries) {
applyTax(theSalaries, Taxes.TAX_TYPE_1);
(...)
getFutureValue(theSalaries, someFutureDate);
(...)
restrictToAMaximum(theSalaries, Maximum.MARRIED_MAXIMUM);
(...)
applyTax(theSalaries, TAXES.TAX_TYPE_3);
(...)
}
public void applyTax(List<Salary> theSalaries, Tax taxToApply) {
for(Salary aSalary : theSalaries) {
aSalary.setAmount(calculateAmountWithTax(aSalary.getAmount(), taxToApply);
}
}
(...)
Run Code Online (Sandbox Code Playgroud)
我需要的是处理这个工资集合,改变金额,但保留金额的所有中间"状态",在表格中向用户显示如下列:
示例报告:( 问题是关于前4行数据,不注意其余部分)
报告示例http://img198.imageshack.us/img198/5651/ue5l.jpg
我的想法:
在类Salary上为每个"部分结果"添加一个属性
public class Salary {
(...)
private BigDecimal originalAmount;
private BigDecimal amountAfterFirstTax;
private BigDecimal amountAfterMaximumRestriction;
(...)
}
Run Code Online (Sandbox Code Playgroud)
问题:
将HashMap添加到Salary类,我可以在其中放置部分结果,并将"key"传递给"step",它必须放置部分结果
public class Salary {
(...)
HashMap<String, BigDecimal> partialResults;
(...)
}
Run Code Online (Sandbox Code Playgroud)
问题:
最后注意:在我的应用程序中还有其他"类似"实体的其他类似情况,所以如果我们能找到一个通用的解决方案,那将是很好的:D
编辑:关于如何建模数据以保持持久性的新疑点
所有的想法都很相似,非常有用.所有这些都与命令模式有关,我认为这是很好的解决方案.但现在我有了一些新的疑虑:
通过更高级别的抽象,我的应用程序执行以下操作:
所以,第二步几乎解决了.我会使用类似命令模式的东西.我现在的问题是如何建模数据以将其持久保存在关系数据库中.因为除了每个操作的部分"结果"之外,还有更多的信息我不需要向用户显示,但我需要将它存储在数据库中.
我的想法是这样的:
薪金表:
id
date // The date of the Salary
finalAmount // The final amount after all the calculations ends
Run Code Online (Sandbox Code Playgroud)
partialResults表:
id
salaryId // The id of the salary which this element represent a partial result
amount // Partial amount
operationCode // Type of operation
operationDescription
Run Code Online (Sandbox Code Playgroud)
但问题是,我的"未来价值"操作作为输出具有以下信息:
但"应用税"操作有不同的信息:
那么,如何为不同的操作保存不同的"输出"信息呢?
您可以创建一个名为SalaryReport的类,它由SalaryReportRow的许多对象组成。
在SalaryReport中,您有一个方法名称calculate (),它执行所有算法。SalaryReportRow可以专门用于满足您需求的多种类型的行。
class SalaryReport {
private List<SalaryReportRow> rows;
private List<SalaryCalculator> calculators;
private HashMap<SalaryCalculator,List<SalaryReportRow>> results;
...
public float getResults() {
}
public void applyCalculators(){
for(SalaryCalculator s : calculators){
results.put(s,s.execute(rows));
}
}
public void setSalaryCalculators(List<SalaryCalculator> calculators){
this.calculators = calculators;
}
public float getCalculation(SalaryCalculator s){
return results.get(s);
}
...
}
Run Code Online (Sandbox Code Playgroud)
在计算税金时,您可以使用策略模式来使您的代码更加灵活。如果您必须结合许多策略,您也可以使用带有策略的复合模式或带有策略的责任链。
abstract class SalaryCalculator implements Calculator {
//Order of children matters
protected List<SalaryCalculator> children = new ArrayList<SalaryCalculator>;
public List<SalaryReportRow> execute(List<SalaryReportRow> rows){
List<SalaryReportRow> result_rows = new ArrayList<SalaryReportRow> (rows);
for(SalaryCalculator s: children){
result_rows = s.execute(result_rows);
}
return result_rows;
}
}
class TaxCalculator extends SalaryCalculator {
public List<SalaryReportRow> execute(List<SalaryReportRow> rows){
List<SalaryReportRow> result_rows = super.execute(rows);
//
}
}
class MaxSalaryCalculator extends SalaryCalculator {
public List<SalaryReportRow> execute(List<SalaryReportRow> rows){
List<SalaryReportRow> result_rows = super.execute(rows);
...
}
}
class MaxSalaryWithTaxCalculator extends SalaryCalculator {
public MaxSalaryWithTaxCalculator() {
children.add(new MaxSalaryCalculator());
children.add(new TaxCalculator());
}
public List<SalaryReportRow> execute(List<SalaryReportRow> rows){
List<SalaryReportRow> result_rows = super.execute(rows);
...
}
}
Run Code Online (Sandbox Code Playgroud)
因此,SalaryReport将有一个名为setSalaryCalculators(List)的方法(您也可以同时使用多个算法),其中 List 是包含所有应用的策略的列表。
您将有更多SalaryReportRows:
这样您就可以轻松计算所有步骤。
当您与存储处理程序通信时,我建议使用带有负责创建和保存对象的接口的DAO 模式。
我希望这会有所帮助。:)