我正在研究访客模式并遇到了这个有用的例子:https://stackoverflow.com/a/2604798/974594。这个帖子非常清楚,非常容易理解,我很难理解最后一部分,从这里开始:
话虽如此,访客通常是矫枉过正,他们有一个 趋势使API复杂化,并且它可能非常麻烦 为每种新行为定义一个新的访问者。
通常,应该使用类似继承的简单模式来代替 游客。例如,原则上我可以编写一个类:
class FruitPricer : IFruitVisitor { public double Price { get; private set; } public void Visit(Orange fruit) { Price = 0.69; } public void Visit(Apple fruit) { Price = 0.89; } public void Visit(Banana fruit) { Price = 1.11; } }
它有效,但与这个微不足道的修改相比有什么优势:
抽象类水果
{ public abstract void Accept(IFruitVisitor visitor); public abstract double Price { get; } }
我不知道他在这里说的是什么。我的意思是,如果他现在想要实现“价格”功能,必须更改/添加到现有代码中(基于此模式方法)?=
答案 0 :(得分:2)
你提到的答案错过了访客的大部分内容。它说“访客习惯于在不牺牲类型安全的情况下实施类型测试”,这是完全错误的。 GOF书中说“访问者可以在不改变其运行元素的类别的情况下定义新操作”。访问者当然可以用于测试除类型之外的对象,以及对不涉及测试的对象执行操作。
“访客过度杀戮”经常被说明,但通常会说人们试图将访客用于其不适合的事情,然后发现 - 这是一种惊喜 - 它并不适用于它。
海报的正确之处在于,他们引用的第二段代码是实现功能的一种更简单的方法,但它忽略了访问者在您不想修改Fruit类时的意图。 / p>
答案 1 :(得分:1)
为每个子类添加特定于类的价格实现。
关键是有时候Visitor
有点矫枉过正,而且可以用抽象的方式添加功能。
现在,Fruit
Price
是否合理是一个不同的问题。 Item
有Item
价格,Fruit
有Fruit
或Item
成为{{1}}的子类,或者他们可能更有意义'复合,或者......