Java 扭曲的抽象工厂

Java 扭曲的抽象工厂,java,abstract-factory,Java,Abstract Factory,我遇到了一个编程问题: 我在EclipseIDE中有两个Java项目:ProjectA和ProjectB。 项目B参考项目A 我在ProjectA:ClassA中声明了一个类,在ProjectB:ClassB中声明了一个类,这样: public class ClassA{ public static Object foo(){ //blah } } public class ClassB extends ClassA{ public static Object foo(){

我遇到了一个编程问题:

我在EclipseIDE中有两个Java项目:ProjectA和ProjectB。 项目B参考项目A

我在ProjectA:ClassA中声明了一个类,在ProjectB:ClassB中声明了一个类,这样:

public class ClassA{
  public static Object foo(){
   //blah
  }
}

public class ClassB extends ClassA{
  public static Object foo(){
    //blah
  }
}
在ProjectA中,我还有一个名为ClientClass的类。此ClientClass先前用于创建并使用ClassA实例。但是现在,基于环境设置,应该为ClientClass提供使用ClassA或ClassB的选项

这似乎是AbstractFactory模式的一个问题,至少我是这么认为的。 我需要创建一个工厂,提供对ClassA或ClassB的访问。ClientClass不应该知道它是ClassA或ClassB。这需要我为ClassA和ClassB创建一个接口

我遇到的问题

  • ClientClass不能直接引用ClassB(没有导入语句或新调用),因为ClassB位于不同的项目中。这可能是一个EclipseIDE限制,但当我将这两个项目视为jar文件时,它对我来说也是有意义的。循环关系是可以避免的
  • 我不能为ClassA和ClassB创建工厂接口和公共接口,然后通过AbstractFactory模式提供ClassA工厂或ClassB工厂。这是因为在ClassA和ClassB上调用的方法是静态的。这些类上的方法需要出现在接口上。但是,在Java中,不能有“抽象静态”修饰符

有人能为这个问题提出一个优雅的解决方案吗?

嗯,这里有很多问题。对于初学者来说,这是最大的一个,这是行不通的,因为在Java中不能重写静态方法。我认为,您所说的目标是能够在运行时用ClassA替换ClassB或B或A或其他,这取决于一些参数。为了做到这一点,您需要能够利用动态分派(或者简单地说,虚拟方法),这将允许运行时系统选择要在运行时执行的方法的内存地址。这在静态方法中是不可能的。您需要使这些方法成为非静态的,这样才能工作。您不必专门设计Java
接口
,但当您使用ClassB扩展ClassA时,您将能够将对象视为一个简单的ClassA对象


综上所述,如果您从方法中移除静态修饰符并使其成为非静态的,那么您就可以在项目A中使用ClassB,而不必像您所说的客户机类中那样使用任何导入语句。然而,在项目A中的某个地方,需要有人知道类B才能实例化它。当然,也就是说,除非您想做一些运行时绑定的工作,并使用字符串动态加载类。这有意义吗?

第一个问题:您的类B和类A的foo方法是静态的。因此,没有任何东西被推翻。如果您打算在ClassB中重写foo,则不应将它们设置为静态

第二个问题是上游需要了解下游。那是不对的,不是吗

这是否是一个抽象因素模式的问题并不重要。设计模式只是让代码遵循已知的结构。这本身并不是目的

现在,为什么项目A中的ClientClass需要了解ClientB

至于工厂,您的工厂需要在项目B中,可以是:

阶级工厂{

公共静态类A CreateTherRightOne(环境设置){//做正确的事情}

}

修复静态修改器后

  • 帕万

Chris,感谢您的详细回复。是的,拥有非静态方法定义将有助于动态调度,但我必须保持方法的静态性——这是一个我无法更改的设计决策。我可能需要设计一种完全不同的机制,通过它我可以将调用路由到ClassA或ClassB。我最终决定清理静态修饰符的混乱,并使用带有动态分派的动态类加载的标准解决方案。将此答案标记为正确答案。谢谢:)帕万,谢谢你的评论。从架构纯度的角度来看,上下游代码点是一个有用的代码点,我喜欢遵循它。在这种特殊情况下,所有的智能内容都发生在ProjectA中,ProjectB中的类提供了一些特定于环境/上下文的信息。所以,在这个特殊的例子中,我需要ProjectA从ProjectB中动态地选择正确的类集,这样事情才能正常运行。如上所述,我有一个维护类及其方法的静态性质的设计需求。