Reputation: 86935
I have a polymorphism structure in my project, and thinking of if it could be valuable to rewrite it to use Visitor Pattern
.
The basic structure is: I have some drawing objects (Rectangle, Ellipse, Line
, more to come) that have of course some behavior in common. The behavior is defined by the interface Drawable
.
So far, dragging should always behave the same, but drawing them selected should differ.
I therefore introduced the abstract Figure
class, which already implements drag()
, but delegates the implementation of drawSelected()
to the extending classes.
Of course the interface will later be extended with additional functions I need, and also additional implementations of Figures will come.
Now my question: Would your rather stick to this design, or switch to Visitor
. And if so, why?
Especially I'm not sure if my present approach is good to have the logic/algorithms for drawing selections inside the objects itself.
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
}
}
Upvotes: 1
Views: 3235
Reputation: 361
The problem you have requires using object structures that are unlikely to change over time; there may be new structures (figures) that may get added but a given object structure (figure) is unlikely to change. Though the structures might not change, you may add more and more operations on the structures and these operations may or may not be common across structures. I think these things make a use-case for using the Visitor
pattern.
To elaborate further, consider the scenario where you are adding a new operation where you require one implementation for one group of figures, another implementation for another group and so on. In current design, you may be able to have only one common implementation in the abstract class (unless you use instanceOf
, but that again is not considered a good practice) and would have to override that implementation in each of the other classes. Where as in case of using the Visitor
pattern, you would always call the visit
method (that would be bound at runtime) and within that you can decide which implementation to call.
In the current design, you may also reach a situation where you have common logic lying in different classes. But in Visitor
pattern, you can maintain various implementations within the visitor class and reuse them in the visit method, so no code duplication.
Visitor
pattern would also give you ease of switching a given figure from one implementation to the other, if required.
Though on adding new classes, you would need to add new implementations to the visitor interface, it will not impact any of you existing classes (figures) or their implementation.
Upvotes: 3
Reputation: 39204
I think the question is a bit overly-broad. We should know a little bit more about your application architecture, features and requirements. I'd just add another point of view to nikpon's one.
Consider the last point:
the classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it's probably better to define the operations in those classes.
So the answer depends on what actually your figures data are and which operations they must implement. I'll give you an example where visitor patterns could be better:
In a case like this there are 2 main consequences:
drawSelected()
, than for every different graphic library you are using, you need to modify drawSelected
implementation on each class(or use a suitable pattern to allow that). In a case like this visitors benefits could be:
Btw this may not be the case, and eventually other pattern can be used to achieve these goals.
Upvotes: 1
Reputation: 56537
[...] and also additional implementations of Figures will come
I think that for this reason alone the visitor pattern is not appropriate for your scenario. Whenever you add a new class to the hierarchy, you'd have to change the visitor interface and all its implementations. The visitor is more appropriate when your hierarchy is stable and it allows you to add extra behaviors easily, just by creating new visitor implementations.
Take a look at the acyclic visitor for an alternative. But think hard about using these patterns, they can make the design more complex than it should be.
Upvotes: 1
Reputation:
Looking at the usages of the Visitor
pattern that is from GoF seems that using that pattern in your case is inappropriate.
Usages
- an object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes.
- many distinct and unrelated operations need to be performed on objects in an object structure, and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When the object structure is shared by many applications, use Visitor to put operations in just those applications that need them.
- the classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it's probably better to define the operations in those classes.
Upvotes: 1