首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >面向对象设计

面向对象设计
EN

Stack Overflow用户
提问于 2013-02-20 06:42:20
回答 1查看 1.4K关注 0票数 2

我被分配了一项任务,那就是写一个简单的程序,为杂货店的顾客打印收据。要知道,基本销售税适用于除书籍、食品和医疗产品以外的所有商品,税率为10%。进口税是对所有进口货物征收的附加销售税,税率为5%,无任何豁免。

样本输入:1本书,10美元,1块进口巧克力,5美元等等。

我想使程序尽可能地面向对象。所以我的等级是这样的:

顶层是抽象类项目(名称、价格),然后我将有类SaleTaxItem (需要支付10%的税)和NonSaleTax项目类扩展自项目。问题是,我是否应该在上面的每个类中创建一个名为isImported的布尔变量,这样我就知道什么时候可以多收费5%了?或者我应该为导入的项创建一个新的类?

这个设计对这个任务非常重要,所以我想让它更完美。谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-20 06:55:45

对于何时使用继承和何时不使用进行了大量讨论。在这种情况下,我不会使用继承来建模您的项目。

为什么?因为在现实生活中,这些税收规则在时间、空间(比如你所处的状态)以及你经营的公司类型上都经常发生变化。如果每次地方政府和联邦政府改变它们的法规时,你都必须改变阶级等级,那么你就注定了--更新将改变你已经拥有实例的类--你的项目。

另一个考虑因素是:如果您使用类(实际上)将销售标记为有税和/或关税,那么您最终将得到一些没有标记接口的项目,还有一些使用多重继承的项目。你需要四节课。再加上一些额外的规则,您就有了一个类爆炸(考虑税额/关税的因素)。

另一种实现是拥有一项财产,即该项目所拥有的税收和关税的征收。你有两门课:

  • 项目
代码语言:javascript
复制
- List: taxes

  • 赋税
代码语言:javascript
复制
- String: name
- Double: percent

税收有许多全球性的例子-- SalesTax和ImportDuty。然后,一个项目在列表中有零个、一个或两个税务实例(列表也意味着税收的应用顺序)。

这最后一种方法在未来也要好得多,以防止税改,包括增加新税。

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

图上有两个“翅膀”:

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

AbstractItem在项目上使用装饰图案,将项目包装成税金层--每一层都由TaxedItem建模。最外层是包装在所有适用的税金中的物品,并且使用装饰器模式,外观和行为就像物品一样,除非价格过高。AbstractItem有几种有用的方法:

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

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

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

TaxAssessor是一个负责协调可适用的税收分配的类.它包含所有TaxOrDuty实例的列表(在本例中,只有一个SalesTax实例和一个ImportDuty实例)。它的方法applyTaxes(Item)迭代这个集合,调用isApplicable()。对于任何返回true的TaxOrDuty,TaxAssessor都会将该项包装在TaxedItem的一个新实例中(当然,该实例引用了TaxOrDuty):

代码语言:javascript
复制
AbstractItem applyTaxes(Item item) {
    taxed = item;
    for (TaxOrDuty td : taxes) {
          if (td.isApplicable(item)) {
              taxed = new TaxedItem(td, taxed);
    return taxed;

所以你的总体答案是:

代码语言:javascript
复制
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>());

这种模式的主要优点是:

  • 新的税收是可填补的。
  • 税收评估和计算算法是税收的一部分,而不是项目,因此非常复杂的税收可以在自己的类中独立而正确地建模。
  • 责任(对我来说)是显而易见的,而且界限也很清楚。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14973770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档