1. 程式人生 > >【設計模式】訪問者模式 Visitor pattern

【設計模式】訪問者模式 Visitor pattern

Today, we are going to talk about one of the most useful design pattern: Visitor pattern.

Advantage

The essential of using visitor pattern is that it allow us to add functions dynamically.

UML

Let’s see the diagram of this pattern (which I downloaded from Wikipedia).
Visitor pattern in UML

Structure

First of all, the class named Client

on the upper left corner is just a normal class (We can have a main function in this class) that allow us to use the instance of concrete visitor classes.

Then the Element class is a class that contains specified data or object or just a super class of a concrete element. Moreover, as I wrote before, we can also a concrete element class that inherit Element

, in the image above, its name is ConcreteElement.
Attention: All classes that accept visitor must have a method

accept(Visitor);

So that it can be visited(return its instance to the Visitor) by the Visitor.
The implementation of a concrete class is just like this:

public Piano extends Element{
    public
void accept(Visitor v){ v.visit(this);//As you can see, here we have returned the instance of Piano. So that it will invoke the suitable function implemented in a visitor. } public void play(){ playThePiano(); } }

Well, perhaps somebody might still not clear about Element and ConcreteElement. For instance, we have a class named Animal which is an Element. Then, we have some classes named Dog, Cat, Elephant that inherited from Animal which are a kind of ConcreteElement.

Last but the most important. We can see there is an interface called Visitor and a ConcreteVisitor which implements the interface. Well, this is the most important things. As we want to add some functions in decades before, we have to modify every class which is of non-sense. However, after Visitor Pattern has been invented, our jobs became much more easier. When we want to add some functions, we just need to create a class that implements Visitor. Then, in this class, we can create different functions that adapt to different objects.

For instance, suppose we have 3 classes called Computer, Piano, Basketball:

public class PlayVisitor implements Visitor{
    public void visit(Computer c){
        c.turnOn();
        c.launchGames();
        c.play();
    }
    public void visit(Piano p){
        p.play();
    }
    public void visit(Basketball b){
        b.callFriends();
        b.takeBall();
        b.play();
    }
}

We can add functions to an existed project without major modification. Just like codes above, we can implement various types of Visitor using the same method that illustrated above.

Then we can create an instance of PlayVisitor in main.

public class Client{
    public static void main(String args[]){
        Piano piano = new Piano();
        Computer computer = new Computer();
        Basketball basketball = new Basketball();

        piano.accept(new PlayVisitor);
        computer.accept(new PlayVisitor);
        basketball.accept(new PlayVisitor);
        //Here we have created 3 different objects that can be played by the user. Then, for each of them, we invoke its accept function as well as put an instance of PlayVisitor as the parameter.
    }
}

Overall, rather than decorator pattern or some difficult patterns, visitor pattern is not very difficult to be implemented. However, it is very useful for those who have need to add many functions. So that I would like to recommend you to use this design pattern.

Example project:

Run result:

Visitor 1 Time of visit: 1.
Found some friends.
Found a ball.
Playing basketball.

Visitor 1 Time of visit: 2.
Computer turned on.
Game launched.
Playing computer game.

Visitor 2 Time of visit: 1.
Playing piano.