Java中的通用方法模式

时间:2012-02-02 00:43:26

标签: java generics design-patterns

我是Java泛型的新手,花了大量时间寻找合适的解决方案(如果有的话)。

我正在尝试设计处理特定类型类对象的适配器。如下所述,CAdapter类仅处理“CClass”对象。我正在尝试提供一个处理大量工作的抽象通用适配器(很像Java集合,如LinkedList)。然后,我为每种需要支持的类型提供了具体的适配器实现。

// Classes

public interface AInterface {
  public String toString();
}

public class BClass extends AInterface  {
  public String toString() { return "BClass "; }
}

public class CClass extends AInterface  {
  public String toString() { return "CClass"; }
}

// Adapters

public interface AdapterInterface<T extends AInterface> {
  public T getInterface();
}

public class BAdapter implements AdapterInterface<BClass> {
  private BClass aInterface = null;
  public BClass getInterface() { return aInterface; }
}

public class CAdapter implements AdapterInterface<CClass> {
  private CClass aInterface = null;
  public CClass getInterface() { return aInterface; }
}

首先,我已经读过,为这样的通用适配器提供CONCRETE实现是不受欢迎的(关于上帝杀死小猫的事情)!也许有人可以扩展这个?

其次,我遇到了动态实例化适配器而没有Java编译器抱怨的问题。例如,我有方法:

public <T extends AInterface> AdapterInterface<T> getAdapter(String type) {
  AdapterInterface<T> result = null;
  if (type.equals("C") {
    result = new CAdapter();
  }
  return result;
}

当然,编译器会抱怨CAdapter不匹配。给定任何类型的AInterface对象,我希望能够加载正确的适配器并适当地处理它。我无法理解工厂模式以实现这一目标。

任何想法都会非常感激。

2 个答案:

答案 0 :(得分:3)

不要在这里使用泛型,协变(或逆变,永远不会记住哪个)返回类型似乎做你想要的:

interface AdapterInterface {
    public AInterface getInterface();
}

class BAdapter implements AdapterInterface {
    private BClass aInterface = null;

    public BClass getInterface() {
        return aInterface;
    }
}

class CAdapter implements AdapterInterface {
    private CClass aInterface = null;

    public CClass getInterface() {
        return aInterface;
    }
}

public AdapterInterface getAdapter(String type) {
    AdapterInterface result = null;
    if (type.equals("C")) {
        result = new CAdapter();
    }
    return result;
}

除非接口中有其他方法,否则你没有提及。以下还编译了通用类:

public
AdapterInterface<? extends AInterface> getAdapter(String type) {
    if (type.equals("C")) {
        return new CAdapter();
    } else {
        // …
    }
}

原始方法无法编译的原因是T是一些扩展AInterface的特定未知类型;它并不意味着“从AInterface延伸的任何类型”。无法静态证明您返回的适配器是调用者所需类型的适配器。

答案 1 :(得分:3)

我的回答有点多余,但是:

任何带&lt; T&gt;的东西意思是“我的来电者知道这种类型是什么,但我不知道”。所以

AdapterInterface<T> result = null;

意味着“我实际上并不知道什么类型的结果,这是我的来电者认为的”。编译器抱怨这个:

result = new CAdapter();

因为这段代码不能假设T是CClass。

事实上,没有强制转换就有没有的方法(声明方法是野蛮的,只是意味着你需要在你调用它的地方投射结果)。演员是告诉编译器的方式“我知道你无法知道这是什么,没关系:我做。相信我。冷静。”。是的,你会收到警告。那没关系。

泛型不会消除所有的施法,但它们只允许你做一次。不需要在整个地方进行演员表演,你只需要在那个地方 - 编码员 - 就​​知道你正在玩各种类型的游戏。所有其余的代码,使用您刚刚创建的适配器的后缀,可以安全地使用泛型类型。