Java 继承 - 为 MVP 模式构建 BaseView

Java Inheritance - Building a BaseView for the MVP pattern

我们正在尝试实现 MVP 模式。因为仅仅拥有一个功能视图就需要相当多的代码,所以我们尝试尽可能多地使用继承。由于我是 Java 的新手,所以我不确定我是否做对了:

因此,我从一个非常简单的接口开始,所有 视图将实现该接口(并且 `getName`` 方法将用于面包屑功能):

public interface IView {    
    public String getName();
}

除此之外,我构建了一个 BaseView,它将用于 大多数 观看次数:

public interface IBaseView extends IView {
    public void addListener(IBaseViewListener l);   

    interface IBaseViewListener {
        void viewEntered(Long id);
    }
}

以及实施

public class BaseView extends CustomComponent implements View, IBaseView{
    private String name = "";
    private List<IBaseViewListener> listeners;

    public BaseView(String name) {
            this.name = name;
            listeners = new ArrayList<IBaseViewListener>();
            buildLayout();
    }

    @Override
    public void addListener(IBaseViewListener l) {
            listeners.add(l);
    }

    protected void buildLayout() {
            this.setId("base_view");
            // initialize layout....
    }

    @Override
    public void enter(ViewChangeEvent event) {
            for (IBaseViewListener l : listeners) {
                    l.viewEntered(id);
            }
    }

    @Override
    public String getName() {
            return name;
    }

}

最后我们有一个 ScaffoldingView 将用于某些视图(主要用于模拟):

public interface IScaffoldingView extends IBaseView{

    public void showTable(AbstractComponent t);

    interface IScaffoldingViewListener extends IBaseViewListener {
            void itemSelected(DataBaseObject selectedObject);
    }
}

和实施:

public class ScaffoldingView extends BaseView implements IScaffoldingView{

    private AbstractComponent table = null;

    public ScaffoldingView(String name) {
        super(name);
    }

    @Override
    protected void buildLayout() {
        // here is a lot more code...
    }

    public void showTable(AbstractComponent t) {
        // here is a lot of code...
    }

}

首先: - 这种方法有意义吗?特别是访问修饰符。说到多态性,我完全无能为力:(

现在,在 ScaffoldingView 中,将有一个专门的 IScaffoldingViewListener。 super class (BaseView) addListener() 方法是否能够处理这些 IScaffoldingViewListeners?

编辑:抱歉,我忘了提到 ViewCustomComponent 是我们使用的第 3 方框架 (Vaadin) 的一些 classes,它提供 enter我们在其中调用eventListeners(Presenter)的事件。

首先,在另一个接口中声明一个接口不太干净,代码有点模糊。

其次,关于扩展CustomComponent,并实现IView和IBaseView的BaseView,首先是一个小细节,如果它实现了IBaseView,你不需要实现IView,因为IBaseView已经扩展了IView,但我看到的更大的问题是:

如果您在某个 class 的某处有一个以 IBaseView 作为参数的方法,但在该函数中您希望能够使用 CustomComponent 中的重写方法,您将无法到,您将只有在 IBaseView 上声明的方法。

如果您想使用 CustomComponent 方法,则必须在该方法内进行强制转换,但这并不干净并且是错误的来源,因为如果将来添加更多 classes 实现 IBaseView 但不扩展 CustomComponent,该函数将抛出异常抱怨转换。

另外,关于 ScaffoldingView,如果您打算将它仅用于测试中的模拟目的,并且您正在使用更多方法扩展 IBaseView 行为,如果您测试一个以 IBaseView 作为参数的方法,您有与以前完全相同的情况,您正在测试的方法将不知道 IScaffoldingView 声明的方法,然后它不会使用它们,并且您的测试不能被信任。

P.D.: 如果你有兴趣学习抽象和继承设计,我建议你查看S.O.L.I.D。原则,网络上有很多关于这些的文献。

编辑:回复您的评论

首先,您需要问问自己,不考虑内部细节、实现、测试或其他任何事情,我的视图有什么行为?他们的行为都一样吗?我真的有不同类型的观点吗?一旦您回答了这些问题并了解了正在发生的事情,您就会了解设计界面层次结构所需的内容,这就是将要暴露给系统其余部分的内容。

您可以(可选地)拥有从这些接口派生的抽象 classes,您可以在其中提供一些初始化、默认值,但是,不要进一步提供比接口提供更多的功能,您可以有一些额外的方法,但仅供内部使用。

然后您可以从接口或中间抽象 classes 派生视图的实际实现(如果您已定义)。

只要把它想象成一个黑盒子,你唯一能看到的就是输入和输出接口,所有其他东西都在那个盒子里,系统的其余部分没有也不应该需要了解一下。

无法真正给你具体的解决方案,因为我不知道你的应用需求。