我们正在尝试实施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...
}
}
首先: - 这种做法有意义吗?特别是访问修饰符。当它来到多态时我完全软弱:(
BaseView
的构造函数中,我正在实现addListener
函数。 现在,在ScaffoldingView
中,会有一个专门的IScaffoldingViewListener
。超类(BaseView)addListener()
方法是否能够处理这些IScaffoldingViewListeners
?
编辑:抱歉,我忘了提及View
和CustomComponent
是我们使用的第三方框架(Vaadin)的某些类,它们提供enter
事件。调用eventListeners(Presenter)。
答案 0 :(得分:1)
首先,在另一个界面中声明一个接口并不是很干净,这会使代码模糊不清。
其次,关于扩展CustomComponent的BaseView,并实现IView和IBaseView,首先是一个小细节,如果它实现IBaseView,你不需要实现IView,因为IBaseView已经扩展了IView,但我看到的更大的问题是:< / p>
如果你在某个类中有某个地方,有一个IBaseView作为参数的方法,但是在你希望能够使用CustomComponent的覆盖方法的那个函数中,你将无法,你只能拥有在IBaseView上声明的方法。
如果你想使用CustomComponent方法,你必须在该方法中进行转换,但这不是干净的并且是bug的来源,因为如果将来你添加了更多实现IBaseView的类但是不扩展CustomComponent,该函数将抛出抱怨有关转换的异常。
此外,关于ScaffoldingView,如果您打算仅在测试中使用它进行模拟,并且您正在扩展IBaseView行为,使用更多方法,如果您测试具有IBaseView作为参数的方法,则您具有相同的与以前一样的确切情况,您正在测试的方法将不会知道IScaffoldingView声明的方法,然后它将不会使用它们,并且您的测试不可信任。
P.D。:如果您有兴趣了解抽象和继承设计,我建议您查看S.O.L.I.D.原则,网上有很多关于这些的文献。
编辑:回复您的评论
首先,您需要在不考虑内部细节或实施或测试或其他任何事情的情况下问自己,我的观点有哪些行为?他们都表现得一样吗?我有不同类型的观点或不是真的吗?一旦你回答了这些问题并了解了正在发生的事情,你将拥有设计界面层次结构所需的内容,以及那将暴露给系统其他部分的内容。
您可以(可选)拥有从这些接口派生的抽象类,您可以在其中提供一些初始化,默认值,但是,不提供比接口提供的更多功能,您可以有一些额外的方法,但仅限于供内部使用。
然后,如果已定义任何视图,则可以从接口或中间抽象类派生视图的实际实现。
只要把它想象成一个黑盒子,你可以看到唯一的东西是输入和输出接口,其他一切都在这个盒子里面,系统的其余部分不需要也不应该知道。
无法真正为您提供具体的解决方案,因为我不了解您的应用程序的需求。