关于何时使用继承以及何时不使用,存在着巨大的讨论。在这种情况下,我会而不是使用继承来建模您的项目。
为什么?因为在现实生活中,这些税收和责任规则在时间,空间(例如你所在的国家)以及你正在运行的公司类型中经常发生变化。如果每当地方政府和联邦政府更改其规定时都必须更改班级层级,那么您注定会失败 - 更新会更改您已拥有实例的班级 - 您的项目。另一个考虑:如果您使用类(有效地)将销售标记为具有税收和/或责任,那么您将最终得到一些没有标记接口的项目,并且一些项目具有多个 - 即使用多重继承。你需要四个班级。添加一些额外的规则,并且你有一个班级爆炸(考虑税种/职责数量的因子)。
另一种实现方式是拥有一个属性,该属性是项目所具有的税收和关税的集合。所以,你有两个班,:
税收有许多全局实例 - SalesTax和ImportDuty。然后,一个项目在列表中具有零个,一个或两个Tax实例(并且该列表还暗示订单纳税被应用)。
这最后一种方法也是更好的适应未来的税制改革,包括增加新税种
编辑一夜之间我有一个改进的建议:
有两种'wings'to the diagram:
- AbstractItem层次结构,处理Item和i税收
- TaxOrDuty层次结构和TaxAssessor中的算法。
AbstractItem在Item上使用decorator pattern,将Item包装在税层中 - 每个层由TaxedItem建模。最外层是包裹在所有适用税款中的物品,并且使用装饰者模式,除了虚高价格外,其外观和行为都与物品相同。该AbstractItem有几个有用的方法:
- 用getPrice():返回全价的项目
- getAllTaxes()的:通过在一个空的列表,以及递归方法在装饰收集TaxOrDuty实例。这对于能够对装饰物品的税收进行分项很重要
- getUntaxedItem():通过装饰物递归直到它找到它返回的物品。这可以轻松从装饰物品中检索原始物品。
在税收方面,有一类TaxOrDuty模拟税收的抽象行为。在这个天真的实现中,每个税都有一个统一的税率,但是您可以轻松地将该行为推到FlatRateTax类中。其方法是:
- 的getRate():返回税收或关税率摘要方法。这是在子类上实现的
- computeTax()方法获取一个项目并根据getRate()计算税金
- isApplicable()是一个抽象方法,如果税项适用于Item,则返回true。这在SalesTax上执行(总是返回true)和ImportDuty(返回Item.isImported)
TaxAssessor是负责协调适用税收分配的类。它包含所有TaxOrDuty实例的列表(在本例中只是SalesTax的一个实例和ImportDuty之一)。它的方法applyTaxes(Item)遍历这个集合调用isApplicable()。对于返回true任何TaxOrDuty,该TaxAssessor包裹项目在TaxedItem(当然它引用TaxOrDuty)的新实例:
AbstractItem applyTaxes(Item item) {
taxed = item;
for (TaxOrDuty td : taxes) {
if (td.isApplicable(item)) {
taxed = new TaxedItem(td, taxed);
return taxed;
所以你的整体答案是这样的:
Item item = new Item("Book", 10.0, false); // New $10 book, not imported
AbstractItem withTaxes = taxAssessor.applyTaxes(item);
double taxedPrice = withTaxes.getPrice();
List<TaxOrDuty> applicableTaxes = withTaxes.getAllTaxes(new List<TaxOrDuty>());
这种模式的主要优点是:
- 新税种是可插拔
- 纳税评估和计算算法是税收的一部分,而不是在项目,所以非常复杂的税收可以在自己的阶级独立且准确地模拟
- 责任是明显的(对我来说),并明确划定
为什么不只是写一个方法'getTax ()'哪些返回10%的SaleTaxItem和10%+ 5%的项目是否可以进口(可能重写?)?我不认为布尔是一个很好的可扩展选择:想象一下,我们引入了新的税收:我们是否需要引入新的布尔值?我们是否需要在int中进行编码? – 2013-02-20 06:45:44
雅我有getTax()其中我目前使用布尔值来决定是否收取5%的进口税。我在Item类中实现了is_import布尔值。如果我不使用布尔值,那么我应该使用什么? – 2013-02-20 07:03:44