The strategy pattern is like a 1:many relationship. When there is one type of object and I want to apply multiple operations to it, I use the strategy pattern. For example, if I have a Video class that encapsulates a video clip, I might want to compress it in different ways. So I create a bunch of strategy classes:
MpegCompression
AviCompression
QuickTimeCompression
and so on.
I think of the visitor pattern as a many:many relationship. Let’s say my application grows to to include not just video, but audio clips as well. If I stick with the strategy pattern, I have to duplicate my compression classes– one for video and one for audio:
MpegVideoCompression
MpegAudioCompression
and so on…
If I switch to the visitor pattern, I do not have to duplicate the strategy classes. I achieve my goal by adding methods:
MpegCompressionVisitor::compressVideo(Video object)
MpegCompressionVisitor::compressAudio(Audio object)
[UPDATE: with Java]
I used the visitor pattern in a Java app. It came out a little different than described above. Here is a Java version for this example.
// Visitor interface
interface Compressor {
// Visitor methods
void compress(Video object);
void compress(Audio object);
}
// Visitor implementation
class MpegCompressor implements Compressor {
public void compress(Video object) {
// ...
}
public void compress(Audio object) {
// ...
}
}
And now the interface and class to be visited:
interface Compressible {
void accept(Compressor compressor);
}
class Video implements Compressible {
// If the Compressor is an instance of MpegCompressionVisitor,
// the system prints "Mpeg video compression"
void accept(Compressor compressor) {
compressor.compress(this);
}