访问者模式 - 添加新的ConcreteElement类很难吗?

时间:2012-06-28 09:32:41

标签: oop design-patterns visitor-pattern

我读了一本关于访客模式的书。它提供了与oodesign's website中相同的类图。

它说添加新的ConcreteElement类很难。但我不明白为什么。据我所知,Concretevisitor定义了一组操作,这些操作必须由concreteElement使用。因此,当我添加一个新元素,它具有我之前定义的相同操作时,我不需要添加任何东西(只是ConcreteElement本身)。如果我添加一个新元素,它没有我之前在访问者中定义的相同操作,我需要添加一个新访问者。但我必须在任何设计模式中做到这一点。

4 个答案:

答案 0 :(得分:2)

嗯,你必须扩展所有访问者。

您有一个调用者,一些需要访问的元素,以及一个元素 - 访问者 - 负责处理各个元素。您的目标是确保元素和调用者的实现得到修复,并通过新访问者扩展功能。

通常你有很多具体的访问者。如果添加要处理的新类型元素,则需要更改所有具体访问者以将其考虑在内。

为什么?

好吧,想象一下来电者是“工厂”,你有“汽车”和“自行车”元素。

对于“Paint”操作,你必须有方法

void process(Car c); // Paint a car
void process(Bike b); // Paint a bike

同样对于“装配”,“包装”,“清洗”等操作

如果添加元素“Scooter”,则必须使用新方法扩展所有操作

void process(Scooter s); // Handle a Scooter

这是一项工作。您也可以点击isse,您添加的元素与其他元素差异很大,您可以轻松地将它们与操作相匹配。

维基百科(http://en.wikipedia.org/wiki/Visitor_pattern)说

  

从本质上讲,访问者可以添加新的虚拟功能   没有修改类本身的类系列;代替,   一个创建一个实现所有适当的访问者类   虚函数的特化。访客拿走了   实例引用作为输入,并通过double实现目标   调度。

这是一种非常抽象的方式来说明我上面说的话。通常你会将这些方法添加到元素中,但如果你不能将这些方法添加到其他方面,并将其传递给进行处理。这是一项额外的工作,但如果情况值得,可能是值得的。

答案 1 :(得分:1)

最近刚出现了一个SO问题。从this问题引用自己,更具体地说是discussion

  

不改变实体集的前提条件(类   你访问)是因为它迫使你实施一个新的VisitXYZ   每个具体的访客。但我从来没有在这个推理中占用太多股票   因为如果你支持持久访问者和文本搜索   访问者,打印访问者和验证访问者,你去   添加一个你想要实现的新实体   功能无论如何。访问者模式(具有公共基类)   只是让编译器找到你忘了为你实现的那些。

所以是的,人们经常说它很难实现额外的混合元素(或实体),但在我看来它是h ..

答案 2 :(得分:1)

如果添加新的具体元素,则所有访问者类都需要为新元素添加新的visit方法。如果您没有使用访问者,则无论如何都必须将等效方法添加到新的具体元素中。

但是为每个访问者添加一个新方法可能比将一组等效方法添加到新元素类更难。原因是访问者经常需要遍历元素树结构,并且可能需要管理自己的状态数据。添加新的visit方法可能需要修改状态数据,这需要考虑新方法如何与其他元素的现有visit方法交互。

如果没有访问者,可以更简单地将等效方法添加到新元素类中,因为您只需要担心新的具体元素的内部状态更具凝聚力。

答案 3 :(得分:1)

基本上,访问者模式是一种数据操纵器,它将

  • 按照一些规则在元素之间遍历
  • 使用这些元素提供的数据进行一些计算和操作

总之,访问者模式将扩展系统功能,而不触及元素类定义。

但这是否意味着如果添加新的具体元素类,则必须修改访问者类?我相信,这取决于访客模式的设计和实施方式。

如果将访问者的所有访问方法分开访问仿函数,并将它们动态绑定在一起,那么在为访问者和被访者扩展系统时,可能会更容易。

以下是我几年前写过的访问者模式的实现,代码有点陈旧,并没有很好地完善,但不知何故有效:)

https://github.com/tezheng/visitor