Visitor pattern implementation in java- How does this look?

情到浓时终转凉″ 提交于 2019-11-30 16:27:33

There is a problem with your code as given. The interface you give has methods such as

public void visitInventory(); 

but you then implement it in XYZValidator as

public void visitInventory(Visitable visitable)

The visitor pattern is a way to implement multiple dispatch in languages that do not do that automatically (such as Java). One of the requirements is that you have a group of related classes (i.e. a set of subclasses with a single super class). You don't have that here, so the visitor pattern is not appropriate. The task you are trying to do, however, is fine, it is just not the Visitor pattern.

In Java, you should think of the Visitor pattern if you have code like

public void count(Item item) {
  if (item instanceof SimpleItem) {
    // do something
  } else if (item instanceof ComplexItem {
    // do something else
  } else ...
}

particulary if the subclasses of Item are relatively fixed.

dfa

Some time ago I wrote something similar for my master thesis. This code is slightly type safe than yours:

interface Visitable<T extends Visitor> {

   void acceptVisitor(T visitor);
}

interface Visitor {

    /**
     * Called before any other visiting method.
     */
    void startVisit();

    /**
     * Called at the end of the visit. 
     */
    void endVisit();
}

example:

interface ConstantPoolVisitor extends Visitor {

    void visitUTF8(int index, String utf8);

    void visitClass(int index, int utf8Index);

    // ==cut==
}

class ConstantPool implements Visitable<ConstantPoolVisitor> {

    @Override
    public void acceptVisitor(ConstantPoolVisitor visitor) {
        visitor.startVisit();

        for (ConstanPoolEntry entry : entries) {
            entry.acceptVisitor(visitor);
        }

        visitor.endVisit();
    }

so yes, I think that this definitely a good and flexible design if, and only if, your data changes slower than your behaviour. In my example the data is Java bytecode, that is fixed (defined by the JVM specification). When "behaviour dominates" (I want to dump, compile, transform, refactor, etc my bytecode) the Visitor pattern let you to change/add/remove behaviour without touching your data classes. Just add another implementation of Visitor.

For the sake of simplicity assume that I must add another visit method to my Visitor interface: I would end in breaking all my code.

As alternative I would consider the strategy pattern for this scenario. Strategy + decorator is a good design for validation.

I'm using a visitor pattern in a different way.. I have a specific Visitor interface for a type of object and this interface declares only one method - for visiting that object.. like this:

public interface TreeNodeVisitor {
    void visit(TreeNode node);
}

the object TreeNode can accept TreeNodeVisitors which means he just calls it's visit method for the node and/or it's children..

The concrete implementation of the visitor implements the visit method and says what the visitor will do.. for example ContryVisitor, InventoryVisitor, etc

This approach should avoid your probleam..

You probably don't want to map a pattern directly to a single interface that everything following that pattern implements. Patterns are NOT Interfaces, they are general plans for implementing a solution.

In your example you would create a StoreVisitor interface and a FileVisitor interface for the different business objects that wish to use the Visitor pattern in the appropriate circumstances.

It might be that different Visitor implementations share common activities - so you could have a superinterface that defines those common functions. You could then code Visitable interfaces to use either the specific Visitable interface or it's superclass as appropriate.

For example, the FileVisitor and SQLTableVisitor interfaces might be a subclass of a DataStoreVisitor interface. Then:

VisitableStore accepts a StoreVisitor,

VisitableFile accepts a Filevisitor, or

VisitableDataStore accepts a DataStoreVistor (which might be an implementation of either FileVisitor or SQLTableVisitor).

  • forgive the random examples, I hope this makes sense.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!