需要帮助使这些类使用访问者模式和泛型
我需要帮助来泛化和实现访问者模式。 我们使用了大量的instanceof
,这很痛苦。我确信它可以修改,但我不知道如何修改。
基本上我们有一个接口 ProcessData
public interface ProcessData {
public setDelegate(Object delegate);
public Object getDelegate();
//I am sure these delegate methods can use generics somehow
}
现在我们有一个实现 ProcessData
的类 ProcessDataGeneric
public class ProcessDataGeneric implements ProcessData {
private Object delegate;
public ProcessDataGeneric(Object delegate) {
this.delegate = delegate;
}
}
现在是一个检索 ProcessData 的新接口
interface ProcessDataWrapper {
public ProcessData unwrap();
}
现在是一个公共抽象类实现包装器,以便可以检索 ProcessData
@XmlSeeAlso( { ProcessDataMotorferdsel.class,ProcessDataTilskudd.class })
public abstract class ProcessDataCommon implements ProcessDataWrapper {
protected ProcessData unwrapped;
public ProcessData unwrap() {
return unwrapped;
}
}
现在实现
public class ProcessDataMotorferdsel extends ProcessDataCommon {
public ProcessDataMotorferdsel() {
unwrapped = new ProcessDataGeneric(this);
}
}
类似
public class ProcessDataTilskudd extends ProcessDataCommon {
public ProcessDataTilskudd() {
unwrapped = new ProcessDataGeneric(this);
}
}
现在,当我使用这些类时,我总是需要执行 instanceof
ProcessDataCommon pdc = null;
if(processData.getDelegate() instanceof ProcessDataMotorferdsel) {
pdc = (ProcessDataMotorferdsel) processData.getDelegate();
} else if(processData.getDelegate() instanceof ProcessDataTilskudd) {
pdc = (ProcessDataTilskudd) processData.getDelegate();
}
我知道有更好的方法来做到这一点,但我不知道如何可以利用泛型和访问者模式。 非常感谢任何帮助。
更新
我想补充一点,这些类只是一个更大的实现的片段。 ProcessData
和 ProcessDataGeneric
是委托之外的东西(ProcessDataMotorferdsel
等等)。委托全部扩展ProcessDataCommon
。
我同意重构可能是最好的选择,但这是 2 年前的生产代码,重构成本很高(时间、测试等)。不过,我愿意这么做。
更新 #2
我尝试启动通用进程,但是遇到编译错误。这就是现在的样子。
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);
}
}
我在线收到编译错误: unwrapped = new ProcessDataGeneric
说
[javac] ProcessDataMotorferdsel.java:52: 不兼容的类型 [javac] 发现:ProcessDataGeneric
我无法弄清楚该错误消息。 ProcessDataMotorferdsel 类扩展了 ProcessDataCommon,因此 IMO 它应该可以工作。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这个答案可能过于简单化,但我认为理想的解决方案将消除您问题中的几乎所有代码。对于试图回答这个问题的人来说,问题在于代码试图解决的真正问题并不清楚剩下的是什么。
重构 instanceof 的常见方法是将子类与“告诉而不是询问”风格的接口结合使用。如果您可以告诉 ProcessDataGeneric 为您完成整个任务,则无需向 ProcessDataGeneric 询问其委托,如下所示:
我什至不确定您是否真的需要 ProcessDataGeneric,因为它所做的只是保存真正的 ProcessData 子类:
...然后您可以像这样使用子类:
...而不必担心委托及其类型。
通常最好使用工厂类而不是构造函数来获取子类实例,特别是在需要计算正确的子类时。
This answer is probably over-simplistic, but I think that nearly all of the code in your question would be eliminated by an ideal solution. The problem for people trying to answer the question is that the real problem that the code is trying to solve isn't clear from what is left over.
A common approach to refactoring away instanceof is to use sub-classes in conjunction with a "tell not ask" style of interface. There is no need to ask ProcessDataGeneric for its delegate if you can tell ProcessDataGeneric to do the whole task for you, like this:
I'm not even sure that you really need ProcessDataGeneric, since all it does is hold the real ProcessData sub-class:
... and then you can use the sub-classes like this:
... without having to worry about delegates and what type they are.
It is often better to use a factory class instead of a constructor to obtain the sub-class instance, particularly if the correct sub-class needs to be calculated.
也许我也错过了一些东西,但
应该是等价的..?正如您所提到的,委托始终是 ProcessDataCommon 类型。
如果 ProcessData#getDelegate() 返回一个
ProcessDataCommon
,您也可以消除剩余的instanceof
检查。Maybe I'm missing something too, but
should be equivalent..? As you mentioned, the delegate is always
ProcessDataCommon
type.If
ProcessData#getDelegate()
would then return aProcessDataCommon
, you could eliminate the remaininginstanceof
check too.如果您的对象已经扩展了所需的目标类,则不必进行强制转换。我的意思是,你可以这样做:
和这个:
你的instanceof Comb 简化为:
You don't have to cast if your object already extends the desired target class. I mean, you can do this:
and this:
And your instanceof comb simplifies to:
我成功了。
查看更新#2并包括此更改:
使所有内容都编译。
I made it work.
Look at UPDATE #2 and including this change:
Made everything compile.