更改静态调用流程 (Java)

Change flow of static call (Java)

我有很多

Foo.a()

但现在我想根据特定条件拆分对 a() 的调用。如果可能的话,我想保持 Foo.a() 调用不变。相反,也许 Foo 可以成为管理流程的工厂,而 FooA 和 FooB 可以扩展 Foo。例如,在 Foo:

private static Class<?> foo;

static {
     if (certain_criteria) {
        foo = SomeUtil.getClass("FooA");
     } else  {
         foo = FooB.class;
     }
     Object obj = foo.newInstance();
     o = (Foo) obj;
 }
...
public static void a() {
    o.a(); //And this should call either FooA.a() or FooB.a()
           //But a() should be accessed in a static way
}

我不能使 Foo 中的 a() 成为非静态的,因为那样我就必须将整个项目中的 100 多个调用更改为 Foo.a()。有没有解决的办法?或者更好的处理流程的方法?

我还尝试使用 foo 来调用 a(),但这会导致编译器错误,因为它的类型是 Class?>。如果我将其更改为

Class<Foo> 

然后我得到

Type mismatch: cannot convert from Class<FooB> to Class<Foo>

您建议使用静态方法 Foo.a() 作为选择和调用适当实现的外观,以 class Foo 选择的可配置方式。您的具体想法似乎依赖于 Foo 的子 classes 来实现支持 Foo.a().

的策略模式

您将至少两个可分离的部分混为一谈:

  1. 实施Foo.a()
  2. 的策略
  3. 选择和实例化特定策略的机制。

特别是,虽然您可能有理由想要使用 Foo 的子 class 部分在真实代码中表示您的策略,但在您的示例代码中没有这样的理由。那么,从示意图上看,您似乎想要这样的东西:

public class Foo {

    private static FooStrategy strategy = FooStrategyFactory.createStrategy();

    public static void a() {
        strategy.doA();
    }
}

interface FooStrategy {
    void doA();
}

当然,你不需要一路走到那里。您最初的想法基本上是让 Foo 本身代替 FooStrategy 服务,并让静态初始化器服务而不是单独的 FooStrategyFactory。这本身并没有错;我只是把它拆开来更清楚地展示每一位的作用。

您还表达了一些具体的实施问题:

If I change it to Class<Foo> then I get

Type mismatch: cannot convert from Class to Class

我上面的方案中的等价物是声明一个 Class<FooStrategy> 类型的变量,并尝试为其分配一个 Class<FooStrategyA> 代表一个 class 实现 FooStrategy . Class 对象的正确类型可以表示任何 class,其实例与类型 FooStrategy 的赋值兼容是 Class<? extends FooStrategy>。无论 FooStrategy 本身是 class 还是接口,这都有效。

I can't call any classes from Foo on foo. "The method a() is undefined for the type Class"

您似乎一直在说您不能在 Class<? extends Foo> 类型的对象上调用 class Foo 的静态方法。事实上,你不能。 class Class 的对象只有 class Class 的方法。尽管您可以使用它们反射性地调用它们所代表的 classes 的方法,但这些方法不能通过 Class 实例本身直接访问。这个问题不会直接出现在我提出的方案中,但它可能出现在工厂或策略实施中。

此外,静态方法不是虚拟的。它们在编译时绑定,基于调用它们的引用 expressions 的正式类型。为了正确应用策略模式,需要的策略实现方法需要是虚拟的:非private和非static.