2

我的任务是编写一个简单的程序来打印杂货店顾客的收据。了解基本销售税适用于所有商品的 10%,但免税的书籍、食品和医疗产品除外。进口税是适用于所有进口商品的附加销售税,税率为 5%,没有豁免。

样本输入:10 美元的 1 本书,5 美元的 1 个进口巧克力棒,依此类推。

我想让程序尽可能面向对象。所以我的层次结构是这样的:

顶层层次结构是抽象类 Item(name,price),然后我将有类 SaleTaxItem(需要支付 10% 税的项目)和 NonSaleTax 项目类从 Item 扩展。问题是我是否应该在上面的每个类中创建一个名为 isImported 的布尔变量,以便我知道何时多收取 5% 的费用?或者我应该为导入的项目创建一个新类?

设计对于这项任务非常重要,所以我想让它变得完美。谢谢!

4

1 回答 1

2

关于何时使用继承以及何时不使用,存在大量讨论。在这种情况下,我不会使用继承来为您的项目建模。

为什么?因为在现实生活中,这些税收和关税规则在时间、空间(例如您所在的州)以及您所经营的公司类型方面经常发生变化。如果每次地方和联邦政府更改法规时您都必须更改类层次结构,那么您注定要失败-更新将更改您已经拥有实例的类-您的项目。

另一个考虑因素:如果您使用类来(有效地)将销售“标记”为具有税收和/或关税,您最终会得到一些没有标记接口的项目,而有些则具有多个 - 即使用多重继承。你需要四门课。添加一些额外的规则,你就有了一个类爆炸(考虑税/关税的数量)。

另一种实现是拥有一个属性,该属性是该项目所拥有的税收和关税的集合。所以你有两个类:

  • 物品

    • 清单:税收
    • 字符串:名称
    • 双倍:百分比

Tax 有许多全局实例 - SalesTax 和 ImportDuty。然后一个项目在列表中有零个、一个或两个 Tax 实例(并且该列表还暗示了税收的应用顺序)。

最后一种方法也更好地适应未来税收变化,包括增加新税

编辑隔夜我有一个改进的建议:

在此处输入图像描述

该图有两个“翅膀”:

  1. AbstractItem 层次结构,处理项目及其税收
  2. TaxOrDuty 层次结构和 TaxAssessor 中的算法。

AbstractItem 在 Item 上使用装饰器模式,将 Item 包装在税层中——每一层都由 TaxedItem 建模。最外层是包裹在所有适用税项中的物品,并且使用装饰器模式,外观和行为与物品一样,只是价格虚高。AbstractItem 有几个有用的方法:

  • getPrice():返回商品的全价
  • getAllTaxes():传入一个空列表,该方法在收集 TaxOrDuty 实例的装饰器上递归。这对于能够逐项列出装饰物品的税款很重要
  • getUntaxedItem():遍历装饰直到找到它返回的项目。这允许从装饰的项目中轻松检索原始项目。

在税收方面,有一个 TaxOrDuty 类,它对一般税收的抽象行为进行建模。在这个简单的实现中,每种税都有一个统一税率,但您可以轻松地将这种行为下放到 FlatRateTax 类中。它的方法是:

  • getRate():返回税率或关税的抽象方法。这是在子类上实现的
  • computeTax() 方法接受一个 Item 并根据 getRate() 计算它的税金
  • isApplicable() 是一个抽象方法,如果税款适用于该项目,则返回 true。这是在 SalesTax(总是返回 true)和 ImportDuty(返回 Item.isImported)上实现的

TaxAssessor 是一个负责协调适用税收分配的类别。它包含所有 TaxOrDuty 实例的列表(在本例中只有一个 SalesTax 实例和一个 ImportDuty 实例)。它的方法 applyTaxes(Item) 遍历这个调用 isApplicable() 的集合。对于任何返回 true 的 TaxOrDuty,TaxAssessor 将 Item 包装在 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>());

该模型的主要优点是:

  • 新税是可插入的
  • 税收评估和计算算法是税收的一部分,而不是在项目中,因此非常复杂的税收可以在自己的类中独立且正确地建模
  • 责任是显而易见的(对我而言)并且界限分明
于 2013-02-20T06:55:45.327 回答