I need help to generify and implement the visitor pattern.
We are using tons of instanceof and it is a pain. I am sure it can be modified, but I am not sure how to do it.
Basically we have an interface ProcessData
public interface ProcessData {
public setDelegate(Object delegate);
public Object getDelegate();
//I am sure these delegate methods can use generics somehow
}
Now we have a class ProcessDataGeneric that implements ProcessData
public class ProcessDataGeneric implements ProcessData {
private Object delegate;
public ProcessDataGeneric(Object delegate) {
this.delegate = delegate;
}
}
Now a new interface that retrieves the ProcessData
interface ProcessDataWrapper {
public ProcessData unwrap();
}
Now a common abstract class that implements the wrapper so ProcessData can be retrieved
@XmlSeeAlso( { ProcessDataMotorferdsel.class,ProcessDataTilskudd.class })
public abstract class ProcessDataCommon implements ProcessDataWrapper {
protected ProcessData unwrapped;
public ProcessData unwrap() {
return unwrapped;
}
}
Now the implementation
public class ProcessDataMotorferdsel extends ProcessDataCommon {
public ProcessDataMotorferdsel() {
unwrapped = new ProcessDataGeneric(this);
}
}
similarly
public class ProcessDataTilskudd extends ProcessDataCommon {
public ProcessDataTilskudd() {
unwrapped = new ProcessDataGeneric(this);
}
}
Now when I use these classes, I always need to do instanceof
ProcessDataCommon pdc = null;
if(processData.getDelegate() instanceof ProcessDataMotorferdsel) {
pdc = (ProcessDataMotorferdsel) processData.getDelegate();
} else if(processData.getDelegate() instanceof ProcessDataTilskudd) {
pdc = (ProcessDataTilskudd) processData.getDelegate();
}
I know there is a better way to do this, but I have no idea how I can utilize Generics and the Visitor Pattern.
Any help is GREATLY appreciated.
UPDATE
I want to add that these classes are just snippets of a much larger implementation.
The ProcessData and ProcessDataGeneric is something that is outside of the delegates (ProcessDataMotorferdsel and so on). The delegates all extends ProcessDataCommon.
I can agree that a refactoring is probably best to do, but this is production code that is 2 years old, and it is costly to refactor (time,testing, etc). However, I am willing to do it.
UPDATE #2
I have tried to start the Generic process, however I am getting compile error. This is how it looks now.
public interface ProcessData<T extends ProcessDataCommon> {
T getDelegate();
setDelegate(T delegate);
}
public class ProcessDataGeneric<T extends ProcessDataCommon> implements ProcessData<T> {
private T delegate;
//Getter & setter
public ProcessDataGeneric(T delegate) {
this.delegate = delegate;
}
}
public class ProcessDataMotorferdsel extends ProcessDataCommon {
public ProcessDataMotorferdsel() {
unwrapped = new ProcessDataGeneric<ProcessDataMotorferdsel>(this);
}
}
I get compile error on line: unwrapped = new ProcessDataGeneric<ProcessDataMotorferdsel>(this); Saying
[javac] ProcessDataMotorferdsel.java:52: incompatible types
[javac] found : ProcessDataGeneric<ProcessDataMotorferdsel>
[javac] required: ProcessData<ProcessDataCommon>
[javac]
I cannot make heads or tails of that error message. The ProcessDataMotorferdsel class extends ProcessDataCommon, so IMO it should work.
Maybe I’m missing something too, but
should be equivalent..? As you mentioned, the delegate is always
ProcessDataCommontype.If
ProcessData#getDelegate()would then return aProcessDataCommon, you could eliminate the remaininginstanceofcheck too.