我的项目中有一个多态结构,并考虑重写它以使用Visitor Pattern
是否有价值。
基本结构是:我有一些绘图对象(Rectangle, Ellipse, Line
,还有更多东西,当然有一些共同的行为。行为由接口Drawable
定义。
到目前为止,拖动应始终表现相同,但选择它们应该有所不同。
因此我引入了abstract Figure
类,它已经实现了drag()
,但是将drawSelected()
的实现委托给了扩展类。
当然接口稍后会扩展我需要的其他功能,并且还会有附加的图形实现。
现在我的问题是:你宁愿坚持这个设计,还是转而使用Visitor
。如果是这样,为什么?
特别是我不确定我现在的方法是否适合在对象内部绘制选择的逻辑/算法。
interface Drawable {
void drag();
void drawSelected();
}
abstract class Figure implements Drawable {
protected int x, y, w, h;
@Override
void drag() {
//implementation always the same for different figures
}
}
class Rectangle extends Figure {
@Override
drawSelected() {
//draw a dashed rectangle around this object
}
}
class Ellipse extends Figure {
@Override
drawSelected() {
//draw a dashed ellipse around this object
}
}
class Line extends Figure {
@Override
drawSelected() {
//draw the line itself dashed
}
}
答案 0 :(得分:2)
您遇到的问题需要使用不太可能随时间变化的对象结构;可能会有新的结构(图)可能会被添加,但给定的对象结构(图)不太可能改变。虽然结构可能不会改变,但您可以在结构上添加越来越多的操作,这些操作在结构中可能相同也可能不常见。我认为这些事情成为使用Visitor
模式的用例。
进一步详细说明,请考虑添加新操作的场景,其中一组图形需要一个实现,另一组需要另一个实现,依此类推。在当前的设计中,您可能只能在抽象类中只有一个通用实现(除非您使用instanceOf
,但这不再被认为是一种好的做法)并且必须在其他每个实现中覆盖该实现类。在使用Visitor
模式的情况下,您总是会调用visit
方法(将在运行时绑定),并且您可以在其中决定调用哪个实现。
在当前的设计中,您可能还会遇到一种情况,即您在不同的类中有共同的逻辑。但是在Visitor
模式中,您可以在访问者类中维护各种实现,并在访问方法中重用它们,因此不需要重复代码。
Visitor
模式还可以让您轻松地将给定数字从一个实现切换到另一个实现。
虽然在添加新类时,您需要向访问者界面添加新的实现,但它不会影响您现有的任何类(图)或其实现。
答案 1 :(得分:1)
查看来自GoF的Visitor
模式的用法似乎在您的案例中使用该模式是不合适的。
使用实例
- 对象结构包含许多具有不同接口的对象类,并且您希望对这些对象执行操作 取决于他们的具体课程。
- 需要对对象结构中的对象执行许多不同且不相关的操作,并且您希望避免“污染” 他们的课程与这些操作。访客可让您保持相关 通过在一个类中定义它们来共同操作。当对象 结构由许多应用程序共享,使用Visitor来放 仅在那些需要它们的应用程序中进行操作。
- 定义对象结构的类很少改变,但是您经常希望在结构上定义新的操作。改变了 对象结构类需要将接口重新定义为all 访客,这可能是昂贵的。如果是对象结构类 经常改变,然后定义操作可能更好 那些课程。
答案 2 :(得分:1)
[...]以及图的其他实现将会出现
我认为仅仅因为这个原因,访问者模式不适合您的场景。每当您向层次结构添加新类时,您都必须更改访问者界面及其所有实现。当您的层次结构稳定时,访问者更合适,并且只需创建新的访问者实现,就可以轻松添加额外的行为。
请查看acyclic visitor以获取替代方案。但是要认真思考使用这些模式,它们会使设计变得更加复杂。
答案 3 :(得分:1)
我认为这个问题有点过于宽泛。我们应该更多地了解您的应用程序架构,功能和要求。我只是为nikpon的另一个观点添加了另一种观点。
考虑最后一点:
定义对象结构的类很少改变,但是经常这样 想要在结构上定义新的操作。改变对象 结构类需要重新定义所有访问者的界面, 这可能是昂贵的。如果对象结构类发生了变化 通常情况下,最好定义那些操作 类。
所以答案取决于你的数据实际是什么以及他们必须执行哪些操作。 我将举例说明访客模式可能更好:
在这种情况下,有两个主要后果:
drawSelected()
内,而不是您正在使用的每个不同图形库,则需要修改每个类的drawSelected
实现(或使用合适的模式来实现)。 在这种情况下,访客的好处可能是:
顺便说一下,情况可能并非如此,最终可以使用其他模式来实现这些目标。