【问题标题】:Avoid instanceof in Java interface implementation在 Java 接口实现中避免使用 instanceof
【发布时间】:2014-05-08 06:34:17
【问题描述】:

假设如下情况:

public interface A {
    void a1();
    void a2();
}

public interface B {
    void b1(A a);
}

public class ImplA implements A {
    // interface methods
    void a1() {};
    void a2() {};
    // ImplA specific methods
    void a3() {};
}

public class ImplB implements B {
    void b1(A a) {
       if(a instaceof ImplA) { // avoid instanceof test and cast 
          ((ImplA)a).a3(); 
       }
    }
}

是否有可能通过一些架构巫术来避免 ImplB.b1() 中的 instanceof 检查? ImplA 和 ImplB 在同一个包中,并且彼此密切相关。我在某处读到,instanceof 的使用暗示了“不太好”的界面设计。有什么建议吗?非常感谢!

【问题讨论】:

  • 没有更多上下文很难说。
  • 您需要什么样的附加信息?
  • Avoiding instanceof in Java 的可能重复项
  • @Raedwald 我读过这篇文章,但我无法将所描述的问题映射到我的案例中。
  • 为避免因重复而被关闭,您需要在问题中解释为什么您的问题实际上不是类似问题的重复。您接受了推荐访问者设计模式的答案。这也是Avoiding instanceof in Java 问题的高票答案之一。

标签: java interface casting instanceof


【解决方案1】:

您可以使用访问者模式来避免 instanceof cast

public interface Visitor {
    void visitImplA(ImplA toVisit);
}

public class VisitorImpl implements Visitor {

    @Override
    public void visitImplA(ImplA toVisit) {
        toVisit.a3();
    }
}

public interface A {
    void a1();
    void a2();
    void accept(Visitor visitor);
}

public interface B {
    void b1(A a);
}

public class ImplA implements A {
    // interface methods
    void a1() {};
    void a2() {};
    // ImplA specific methods
    void a3() {};

    void accept(Visitor visitor) {
        visitor.visitImplA(this);
    }
}

public class ImplB implements B {
    void b1(A a) {
        a.accept(new VisitorImpl());
    }
}

这将消除您所有的 instanceof 检查并将它们划分为访问者和实现类,这种模式在大多数 instanceof 检查之后您将执行相同操作的情况下就足够了,否则您需要一个访问者接口的很多实现

【讨论】:

  • 这听起来很合理。我将对此进行更深入的研究。谢谢。
  • 在我看来这种模式更好用,当 ImplA 和 ImplB 不知道彼此并且目标是保持这种方式时。就我而言,它们彼此密切相关(通过组合)。
  • 是的。避免 instanceof 检查的最简单方法是在同一位置传递 ImplA 对象或将 a3() 广告添加到接口,但这些是取决于上下文的设计决策。
【解决方案2】:

您想要的 VooDoo 是作曲。您可以使用访客设计模式来解决这个问题。但是当你使用它时会有一些惩罚。或者您可以创建用于调用该 a3 方法的其他接口。

情况各不相同。问题的原因可能是您的架构不完整,并且您尝试做一些奇怪的事情或者您的班级执行了很多事情。

【讨论】:

  • 如果当前的 API 需要改变,那么这个额外的接口会是什么样子? “不包括”是什么意思。由于 ImplB 处理的事件,ImplB 想要触发 ImplA 上的状态更改。
猜你喜欢
  • 2011-09-03
  • 2013-03-05
  • 2013-12-30
  • 1970-01-01
  • 2012-04-18
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
相关资源
最近更新 更多