3

我有一个超类,我想将一个静态方法转发getInstance()给所有子类。

在创建子类的实例时,我会在超类中注册该实例(可能使用哈希表,其中键基于getClass())。然后,我希望使用前面提到的静态方法 ( getInstance),其中超类方法将返回正确类型的实例。

比如我有一个超类A,一个子类B扩展了A。我想写一个静态方法A.getInstance();当从 B ( B.getInstance()) 调用时,我希望它返回我之前存储的 B 实例。

这有点难以解释,但我会经常使用这个超类,而且我宁愿不在getInstance每个子类中编写一个方法。

我将如何去做这样的事情?

编辑:我刚刚意识到我的问题可能被误解为创建对象的新实例。我已经创建了实例,我希望获取该类的现有实例

4

6 回答 6

3

正如许多其他人在评论中指出的那样,静态方法无法实现您尝试做的事情。此外,您应该尽可能避免使用静态方法,因为它们可能导致测试和维护的噩梦 (*)。

您将方法命名为“getInstance”,所以我您想要做的是工厂模式和单例模式的混合。以下是一些帮助您开始了解这些模式的信息:

单例:http
://en.wikipedia.org/wiki/Singleton_pattern 工厂方法:http
://en.wikipedia.org/wiki/Factory_method_pattern 抽象工厂:http ://en.wikipedia.org/wiki/Abstract_factory

现在两者都不应该手动编码 (*) - 看看像 Google Guice 或 Spring 这样的优秀“依赖注入”(DI) 容器。我不是 100% 确定您到底想要实现什么,但看起来 DI 容器会为您完成。

编辑:这是对问题编辑的回应。您想要接收子类的缓存实例。在这种情况下,我仍然建议不要使用静态方法。您可以创建“BCache”类的单例实例(使用 DI 容器或手动编程),然后使用此缓存对象查找已注册的对象。使用 Guice 作为 DI 容器,它可能看起来像这样(警告,未经测试):

@Singleton
public class BCache {
    private Map<Class<? extends B>, B> cache = ...;

    public <T> T getInstance(Class<? extends T> type) {
        return (T) cache.get(type);
    }
}

不过,我仍然认为可以使用 DI 容器完全摆脱缓存类。同样,这是未经测试的代码,使用 Guice,但它可能看起来像这样:

@Singleton
public class A extends B {
    public A() {
        //I am not sure if you need to register in this case, because your
        //DI container keeps track of the singleton instances.
        super.register(this);
    }
}

public class SomeClassUsingA {
    @Inject private A a;
}

(*) 请注意“所有的概括都是错误的”,也就是说,在某些项目中它可能有意义,但在大多数情况下它不会。

于 2013-01-16T08:06:01.270 回答
1

您无法以良好的 OOP 方式使用静态方法完全按照您的意愿行事。您可以使用反射或一堆if .. else if.

但是,您应该使用一些定义明确的设计模式,例如Abstract fectoryFactory method。这是你应该走的路,就像有人说“不要发明温水”。

于 2013-01-16T08:11:07.840 回答
1

您始终可以将 subClass 实例分配给 superClass 引用。因此,您的超类的静态方法可以设置或获取子类实例。但请确保在使用前转换返回的实例。

public class A {
    private static A a;

    /**
     * @param a the a to set
     */
    public static void setA(A a) {
        A.a = a;
    }

    /**
     * @return the a
     */
    public static A getA() {
        return a;
    }


public class B extends A {
    private int index = 0;

    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * @return the index
     */
    public int getIndex() {
        return index;
    }

用法:

public static void main(String[] args) throws Exception {
        B b = new B();
        A.setA(b);

    B c = (B) A.getA();
    System.out.println(c.getIndex());
}
于 2013-01-16T08:18:48.007 回答
0

静态方法不知道使用哪个类来调用它们。例如,如果您有扩展 A 并在其中static getInstance()实现的A 和 B 类,那么无论您调用using还是A没有区别。此外,尝试调用会产生编译警告(至少在 Eclipse 中)。getInstance()ABB.getIntance()

但是,您可以将类作为参数传递getInstance()

public class A {
    public static <T extends A> T getInstance(Class<T> clazz) {
        return clazz.newInstance(); // I do not catch exceptions here: do it yourself
    }
}

public class B extends A {
}

...............
B b = A.getInstance(B.class);
于 2013-01-16T08:08:16.480 回答
0

getInstance()在超类中更改形式getInstance(String class)

public static A getInstance(String class){
if(class.equals("A")){
RegisterObject(...);//User defined method
return new A(...);
}
else if(class.equals("B")){
RegisterObject(...);//User defined method
return  new B(...);
}
else if(class.equals("C")){
RegisterObject(...);//User defined method
return  new C(...);
}
//... and so on

}
于 2013-01-16T08:04:58.847 回答
0

你可以这样做,

 class A{
     public static A getInstance(){
     return new A();
   }

  @Override
  public String toString() {
   return "inside A";
   }
 }

 class B extends A{
public static A getInstance(){
  return new B();
 }

   @Override
   public String toString() {
      return "inside B";
   }
 }

内部主要:

   public static void main(String[] args) {
  A a1 = A.getInstance();
  A a2 = B.getInstance();
      System.out.println(a1.toString());
  System.out.println(a2.toString());
   }
于 2013-01-16T08:13:34.633 回答