【发布时间】:2010-11-02 10:13:24
【问题描述】:
我正在寻找访问者模式的替代方案。让我只关注模式的几个相关方面,同时跳过不重要的细节。我将使用 Shape 示例(抱歉!):
- 您有一个实现 IShape 接口的对象层次结构
- 您有许多要对层次结构中的所有对象执行的全局操作,例如绘图、WriteToXml 等...
- 很想直接潜入并将 Draw() 和 WriteToXml() 方法添加到 IShape 接口。这不一定是一件好事 - 每当您希望添加要对所有形状执行的新操作时,都必须更改每个 IShape 派生类
- 为每个操作实现一个访问者,即一个 Draw 访问者或一个 WirteToXml 访问者,将该操作的所有代码封装在一个类中。然后添加一个新操作就是创建一个新的访问者类,该类对所有类型的 IShape 执行操作
- 当您需要添加新的 IShape 派生类时,您基本上遇到了与 3 中相同的问题 - 必须更改所有访问者类以添加处理新 IShape 派生类型的方法
您阅读访问者模式的大多数地方都指出,第 5 点几乎是该模式起作用的主要标准,我完全同意。如果 IShape 派生类的数量是固定的,那么这可能是一种非常优雅的方法。
因此,问题在于添加新的 IShape 派生类时 - 每个访问者实现都需要添加一个新方法来处理该类。这充其量是令人不快的,在最坏的情况下是不可能的,并且表明这种模式并不是真正为应对此类变化而设计的。
那么,问题是有没有人遇到过处理这种情况的替代方法?
【问题讨论】:
-
顺便说明一下,因为您不太可能更改您的语言:有些语言直接支持多个调度泛型函数。
-
好问题。我只是想提供一个对位。有时,您对 (5) 的问题可能是件好事。当我有一些在定义新的 IShape 子类型时必须更新的功能时,我会使用访问者模式。我有一个 IShapeVisitor 接口,它定义了需要哪些方法。只要使用新的子类型更新该接口,我的代码就不会在关键功能更新之前构建。在某些情况下,这可能非常有用。
-
我同意@oillio,但您也可以将其作为 IShape 上的抽象方法强制执行。访问者模式在纯 OO 语言中为您购买的是函数的局部性(与类的局部性),因此是关注点的分离。在任何情况下,当您想强制添加新类型时,使用访问者模式应该在编译时显式中断!
-
“必须更改所有访问者类以添加处理新 IShape 派生类型的方法”:我不会说这是一个“问题”。我会说这是您设计中非常好的安全性。它保证在您执行每种类型特定操作的每个地方都考虑新添加的类(即:在我们定义访问者的每个地方......如果您不考虑新添加的类型,编译器将不会放开你……)。
标签: oop design-patterns visitor-pattern