访问者设计模式 - 返回类型

11

我使用了访问者设计模式来解决我们系统中的一个问题。我参考了DoFactory网站这个YouTube视频中的实现方法。

在DoFactory的例子中,访问者使用了一个返回类型为"void"的方法;而在YouTube视频中,作者使用了"double"。

我的疑问:
将解决方案呈现给公司CTO后,他同意将其称为访问者,但他认为如果访问者不是如GoF所述的"void",那么它就像是滥用了真正的访问者模式。

问题:
访问者模式是否需要返回"void"?
我的意思是,为了符合DoFactory(GoF)所描述的"真正的访问者模式",它必须是"void",还是可以是任何返回类型,并且仍然可以被称为"真正的访问者模式"?


1
很好知道其他作者选择返回double而不是什么都不返回(void)的原因,然后分析这些原因在这种情况/场景中是否有效。大多数时候,谈论纯粹这样或那样的模式有点低效。只需使用最适合您的方法即可,不必过多担心如何称呼它。如果您将它们称为访问者模式之一,大多数人仍会同意并理解您所说的内容:这是首要目标。让我们看看…定义“真实”。 - Leandro
5
我在Programmers.SE上写了一篇回答,谈到了这个问题。简而言之,GoF设计模式书中的例子代码实际上返回任意对象,但由于该代码是使用动态语言Smalltalk编写的,因此这一点很容易被忽略。 C ++示例代码必须使用void,因为该语言的语义限制,并不是因为void返回类型是访问者模式的核心特征。 在Java中,我们可以使用泛型来以类型安全的方式返回非void类型。 - amon
1
又一个原因,为什么不应该让CTO编写代码 :-) - Ostati
1
@Ostati 我认为这与CTO职位无关。虽然可能存在CTO不应该自己编码的原因,但我认为这只是在高级工程师之间的任何设计/审查讨论中可能发生的特定设计模式的小误解。 - Qw3ry
@Qw3ry 部分是玩笑,部分是真的,部分是你想要的任何东西,但是是的,只要他们有能力以正确的方式执行,任何人都可以做任何他们想做的事情。 - Ostati
1个回答

16

设计模式的主要作用是指导如何解决常见的计算机科学问题。您可以根据自己的需要任意偏离“真实”实现。

至于您提到的youtube视频示例,该作者展示了如何使用访问者模式来为不同类型的商品计算税费。每个visit方法返回一个双精度浮点数,表示包括税费在内的每种商品的费用。然后创建不同的Visitor实现,以展示如何采用不同的方式计算税费(普通税 vs 节日税等),而不改变代码。

这个例子只是一个“玩具”问题,旨在以易于理解的方式教授访问者模式-它确实做得很好。

虽然我说您可以自由偏离GoF实现,但模仿此视频中的代码可能并不是一个好主意。视频中有一些东西在真正的程序中使用会产生问题。例如,使用double表示货币。 我认为返回双精度浮点数(表示货币)只是为了快速展示访问者模式的工作原理,您可能不应该这样使用它。

如果您想修改视频中的代码以返回void,则最简单的解决方案是在TaxVisitor中设置一个私有字段来累加总值,并在每个visit方法内递增该字段。然后添加一个getter以获取最终总额。

作者在他的访问者示例中还明确调用了每个食品项,这并没有展示出访问者模式的强大之处。我会创建一个包含可访问项的容器对象,并且其accept方法将访问收据中的每个商品。

GroceryList groceries = new GroceryList();

groceries.add(new Milk(...));
groceries.add(new Liquor(...));
   ...


 TaxVisitor visitor = new TaxVisitor();

 visitor.accept(groceries);


 Money tax = visitor.getTax();

 Money preTaxTotal = groceries.getTotalPreTax();

 Money total = preTaxTotal.plus(tax);

//or compute tax during tax holiday
TaxVisitor holidayVisitor = new TaxHolidayVisitor();
  holidayVisitor.accept(groceries);


 Money holidayTax = holidayVisitor.getTax();

  Money holidayTotal = preTaxTotal.plus(holidayTax);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接