繁体   English   中英

避免在基于工厂的通用MVP框架中进行转换

[英]Avoiding cast in generic factory-based MVP framework

我试图在MVP模式中实现一种将View和Presenter分离的方法,以提供一个框架,这正是这样做的,但在一点之后我感到困惑。

背景

我有一个View接口,其中包含连接的演示者的泛型类型,反之亦然。 这些接口将由实现开发人员扩展。 具体的界面对这个问题不感兴趣,但这些界面的类定义如下所示:

public interface Presenter<T extends View>

public interface View<T extends Presenter>

这个想法是View和Presenter都知道对立的界面。

对于使用此结构,开发人员应提供工厂,实例化他想要显示的视图和处理此视图的Presenter。 他把它们都给了一个名为SuperController的类。 它们与View的类相关联。

创建Presenter的PresenterFactory接口没有参数,并返回Presenter实现,并查看以下内容:

public interface PresenterFactory<T extends View> {

    <S extends Presenter<T>> S create();

}

创建View的ViewFactory接口基于Presenter创建View实现,并查看以下内容:

public interface ViewFactory<T extends View, S extends Presenter<T>> {

    T create(S presenter);

}

问题

我遇到的问题如下:

我想提供一个TestView和TestPresenter的示例。 那些看起来像这样:

public interface TestPresenter extends Presenter<TestView> {...}

public interface TestView extends View<TestPresenter> {...}

此外,还提供了ViewFactory,如下所示:

class TestViewFactory implements ViewFactory<TestView, TestPresenter> {

    @Override
    public TestView create(TestPresenter presenter) {
        return new TestViewImpl(presenter);
    }
}

这是TestPresenterFactory:

private class TestPresenterFactory implements PresenterFactory<TestView> {

    @Override
    public <S extends Presenter<TestView>> S create() {
        return new TestPresenterImpl();
    }
}

此代码无法编译。 问题是TestPresenterFactory的返回值。 Java说,它期望S而不是TestPresenterImpl。 此外,转换为TestPresenter将无法正常工作。 然而,施放到S 起作用。 它可以编译并运行成功,但这不是我希望实现开发人员做的事情。

为什么会出现这个问题? 为什么铸造到具体界面不起作用? 在我看来,这应该工作,因为TestPresenterImpl实现了TestPresenter,它扩展了通用类型TestView的Presenter,但它不可编译。


下面工作。 如果您更改PresenterFactory定义,如下所示:

public interface PresenterFactory<T extends View, S extends Presenter<T>> {

    S create();

}

示例实现现在看起来像这样:

private class TestPresenterFactory implements PresenterFactory<TestView, TestPresenter> {

    @Override
    public TestPresenter create() {
        return new TestPresenterImpl();
    }
}

它可以编译和运行,就像我在上面的例子中转换为S一样。

但是,这不是我想要的。 泛型类型声明是多余的。 让实现开发人员声明View 演示者,仅创建Presenter看起来很尴尬。 如果类型可以在该方法中推断,那将是非常好的。

另外,我不想强​​制实现开发人员转换为S.

这有更优雅的方式吗?


编辑

提出一个问题作为重复,我想与这个问题保持距离。

由此产生的问题与Producer Extends Consumer Super无关。 我有两个生产商(工厂)在使用。 这两个都产生了一个类。 一个依赖于另一个类(View依赖于Presenter),而另一个依赖于Presenter(Presenter可以使用默认构造函数实例化)。 所有受尊重的接口都具有T扩展XYZ定义,以允许生成继承该接口的接口(Presenter或View)。

这里真正的问题是ViewFactory中的泛型可以由Java推断。 两个泛型类型都在类定义中声明。 在PresenterFactory中,Java无法推断出方法级泛型。 尽管如此,泛型类型与视图工厂中的类型相同<S extends Presenter<T>> ; 在该方法中,不能推断出这种类型。

解决方案是要么强制转换(我不希望使用开发人员这样做),要么在类定义中声明PresenterType(这似乎是多余的。唯一感兴趣的是,视图是定义的,任何Presenter为该视图返回)。

我的问题是我可以做些什么来解决由extends子句引起的所述问题?

首先,这将解决问题:

interface PresenterFactory<T extends View, S extends Presenter<T>> {
    S create();
}

class TestPresenterFactory implements PresenterFactory<TestView, TestPresenterImpl> {

    @Override
    public TestPresenterImpl create() {
        return new TestPresenterImpl();
    }
}

但我仍然不喜欢:

  • View和Presenter之间的循环依赖;
  • 使用原始类型:实际上,如果你在各自的接口声明中盲目地使用View<?>Presenter<?> ,那么它将再次无法编译( TestPresenterFactory将失败)。

--- 编辑 ---

那么如何解决最后2点以及原始问题呢:

interface Presenter<P extends Presenter<P, V>, V extends View<P, V>> {

}

interface View<P extends Presenter<P, V>, V extends View<P, V>> {

}

interface PresenterFactory<P extends Presenter<P, V>, V extends View<P, V>> {

    P create();

}

interface ViewFactory<P extends Presenter<P, V>, V extends View<P, V>> {

    V create(P presenter);

}

interface TestPresenter extends Presenter<TestPresenter, TestView> {}

class TestPresenterImpl implements TestPresenter {

}

interface TestView extends View<TestPresenter, TestView> {}

class TestViewImpl implements TestView {

    public TestViewImpl(Presenter<?, ?> presenter) {
    }
}

class TestViewFactory implements ViewFactory<TestPresenter, TestView> {

    @Override
    public TestView create(TestPresenter presenter) {
        return new TestViewImpl(presenter);
    }
}

class TestPresenterFactory implements PresenterFactory<TestPresenter, TestView> {

    @Override
    public TestPresenter create() {
        return new TestPresenterImpl();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM