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...
}
}
首先:
- 这种方法有意义吗?特别是访问修饰符。说到多态性,我完全无能为力:(
- 我不太确定 EventListener 的处理方式。例如:在
BaseView
的构造函数中,我正在实现 addListener
函数。
现在,在 ScaffoldingView
中,将有一个专门的 IScaffoldingViewListener
。 super class (BaseView) addListener()
方法是否能够处理这些 IScaffoldingViewListeners
?
编辑:抱歉,我忘了提到 View
和 CustomComponent
是我们使用的第 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 派生视图的实际实现(如果您已定义)。
只要把它想象成一个黑盒子,你唯一能看到的就是输入和输出接口,所有其他东西都在那个盒子里,系统的其余部分没有也不应该需要了解一下。
无法真正给你具体的解决方案,因为我不知道你的应用需求。
我们正在尝试实现 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...
}
}
首先: - 这种方法有意义吗?特别是访问修饰符。说到多态性,我完全无能为力:(
- 我不太确定 EventListener 的处理方式。例如:在
BaseView
的构造函数中,我正在实现addListener
函数。
现在,在 ScaffoldingView
中,将有一个专门的 IScaffoldingViewListener
。 super class (BaseView) addListener()
方法是否能够处理这些 IScaffoldingViewListeners
?
编辑:抱歉,我忘了提到 View
和 CustomComponent
是我们使用的第 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 派生视图的实际实现(如果您已定义)。
只要把它想象成一个黑盒子,你唯一能看到的就是输入和输出接口,所有其他东西都在那个盒子里,系统的其余部分没有也不应该需要了解一下。
无法真正给你具体的解决方案,因为我不知道你的应用需求。