Java中的泛型策略模式

时间:2011-11-14 00:59:53

标签: java oop generics

所以我正在尝试创建一个带有泛型函数的接口,以便被子类覆盖,但我找不到这样做的方法。

我认为一段代码会更明确:

interface Agent<A extends Agent<A>> {
    <W extends World> Iterable<Action<A,W>> percepts(W world);
    <W extends World> void takeAction(Action<A,W> action, W world);
}

abstract class StrategistAgent<A extends StrategistAgent<A>> implements Agent<A> {
    abstract public <W extends World> AgentStrategy<A,W> getStrategy();
    abstract public <W extends World> void setStrategy(AgentStrategy<A,W> strategy);

    @Override
    <W extends World> Iterable<Action<A,W>> percepts(W world) {
        return getStrategy().run(this, world);
    }
}

interface AgentStrategy<A extends StrategistAgent<A>, W extends World> {
    Iterable<Action<A,W>> run(A agent, W world);
    void init(A agent, W world);
}

错误:AgentStrategy类型中的方法run(A,World)不适用于参数(StrategistAgent,W)

但我不能写:

StrategistAgent<A extends StrategistAgent<A>, W extends World>

编辑:好的,我按照Mark Peters的建议删除了setStrategy方法。应该现在正在工作..

1 个答案:

答案 0 :(得分:2)

正确的问题,正如您现在可能已经想到的那样,没有任何迹象表明您的错误发生在哪里,thisA的一个实例。当我说Generics真的不是为了这种自我引用的打字时,我就是这样做的。

但是你的设计中也存在其他问题。对于初学者,您在设置策略时接受的W可能与调用W时获得的percept完全不同。

那你前进的方向是什么?好吧,我再次认为这取决于您的胶水代码,创建代理和策略并将它们组合在一起的东西。

由于该胶水代码很可能确切地知道它正在处理的代理和策略的类型,因此您可能甚至不会使setStrategy抽象受益。一旦它不是抽象的,你就可以在每个子类中处理它。

您的子类实际上只需要一个受保护的方法getStrategy。如果你强迫所有子类提供它,你也可以强迫他们返回A

abstract class StrategistAgent<A extends StrategistAgent<A>> implements Agent<A> {
    protected abstract <W extends World> AgentStrategy<A,W> getStrategy();
    protected abstract A getSelf();

    @Override
    public <W extends World> Iterable<Action<A,W>> percepts(W world) {
        return this.<W>getStrategy().run(getSelf(), world);
    }
}

所以这是一个解决方案。我不得不考虑更多优雅的想法。