I\'ve made some research trying to develop a type conversion framework which provides an ability to convert instances of a source class (e.g., Foo) to instances of result cl
You could just ditch Visitor Pattern as there is a better solution for Java.
The visitor pattern use double-dispatch, that usually goes like this:
public class ParentDataModel
{
public void accept(Visitor visitor)
{
visitor.visit(this);
}
}
public class ChildDataModel extends ParentDataModel
{
// no need to implement accept() by the child itself
}
public class Visitor
{
public void visit(ParentDataModel model)
{
// do something with it
}
public void visit(ChildDataModel model)
{
// do something with it
}
}
Why on earth a data model need to be aware of visitor? A data model should only hold the data relevant to the model.
What if you need to do something with, say Number, Double, that are from the JDK.
Even say you're willing to make a wrapper around each object you need in your project, it's hell tedious, and think about how many classes you will have to refactor to get this to work.
public class NumberWrapper
{
private Number value;
public void accept(Visitor visitor)
{
visitor.visit(value);
}
}
public class DoubleWrapper
{
private Double value;
public void accept(Visitor visitor)
{
visitor.visit(value);
}
}
public class Visitor
{
public void visit(Number value)
{
// do something with it
}
public void visit(Double value)
{
// do something with it
}
}
public static class SuperConsumer implements Consumer
{
private Map, Consumer>> consumers = new HashMap<>();
private Consumer> unknown = o -> System.err.println("Unknown object type");
public SuperConsumer()
{
consumers.put(Number.class, o -> consumeNumber(o));
consumers.put(Double.class, o -> consumeDouble(o));
}
private void consumeNumber(Number value)
{
System.out.printf("Consuming: %s\n", value.getClass().getName());
}
private void consumeDouble(Double value)
{
System.out.printf("Consuming: %s\n", value.getClass().getName());
}
private Consumer findConsumer(Object object)
{
Consumer consumer = consumers.get(object.getClass());
Class superClazz = object.getClass().getSuperclass();
while (consumer == null && superClazz != Object.class)
{
consumer = consumers.get(superClazz);
superClazz = superClazz.getSuperclass();
}
Class>[] interfaces = object.getClass().getInterfaces();
for (int i = 0; consumer == null && i < interfaces.length; i++)
{
consumer = consumers.get(interfaces[i]);
}
return consumer;
}
@Override
public void accept(Object object)
{
Consumer consumer = findConsumer(object);
if (consumer == null)
{
consumer = unknown;
}
consumer.accept(object);
}
public static void main(String[] args)
{
Consumer consumer = new SuperConsumer();
Arrays.asList(new Double(1.0), new Integer(1), new Float(1.0f)).forEach(o -> consumer.accept(o));
}
}