我有以下类的层次结构:
public interface Message
public interface V2Message extends Message
public interface V3Message extends Message
我定义了另一个接口来验证消息。
public interface Validation {
boolean validate(Message message);
}
每个实现Validation
的类都可以处理V2和/或V3消息,因此在我的实现中,我必须区分我想要验证的消息类型,因为代码会有所不同。
public class MyValidation implements Validation {
public boolean validate(Message message) {
if(message instanceof V2Message) {
return validateV2((V2Message)message);
} else if (message instanceof V3Message) {
return validateV3((V3Message)message);
}
}
我想知道是否有办法取消使用instanceof
。
答案 0 :(得分:4)
一种方法是实施Visitor pattern。定义MessageVisitor接口:
public interface MessageVisitor {
boolean visit(V2Message message);
boolean visit(V3Message message);
}
然后重新定义Message接口以包含方法:
public void visitMessage(MessageVisitor visitor);
然后,每个具体的Message类都将实现visitMessage
方法,如下所示:
public void visitMessage(MessageVisitor visitor) {
visitor.visit(this);
}
由于这是在每个具体子类中定义的,因此编译器将调用visit
的正确版本。
如果您需要的只是验证,这可能会有点过分。但是,如果您要实现其他需要以不同方式处理不同类型消息的操作,那么它的优势在于您可以在不更改消息类的情况下实现每个消息。本文开头的文章链接中描述了优缺点。
答案 1 :(得分:2)
你可以给Validate
两种方法而不是一种方法:
public interface Validation {
boolean validate(V2Message message);
boolean validate(V3Message message);
}
这也会阻止传递一个简单的Message
作为运行时错误。这也是一个更准确的API,因为您已经说过Validation
实施无法处理Message
,只能处理V2Message
和V3Message
。
答案 2 :(得分:2)
public interface Message{
boolean validate();
}
实施Message
的具体课程将负责了解他们被问到validate()
的时间。
答案 3 :(得分:0)
这让我觉得相当紧密,需要有关类/接口内部工作的知识才能“验证”它。如果可能,您应该使Message
接口有自己的验证。
这会产生这样的结果:
public interface Message{
boolean validate();
// Stüfe
}
但是,它可能会在如何验证之间存在根本性的差异。 (已知在观察者模式中发生类似情况)。在这种情况下,我可能会使用重载来区分。
public interface Validation {
boolean validate(V2Message message);
boolean validate(V3Message message);
boolean validate(Message message); // may not be needed, but in case you want
// still handle generic Messages, you will
// definitely need it.
// Stüfe
}
如上所述,这可能会带来更多编译时错误。除了您已经获得的内容之外,它不会提供任何实质性的反馈 - 您的代码将导致与传递通用Message
相同的错误。