Java 模型视图演示器和复合视图
我试图在JavaSwingUI应用程序中遵循MVP(特别是被动视图)模式 应用程序的基本设计是一个向导控件。屏幕分为两个主要部分:Java 模型视图演示器和复合视图,java,design-patterns,swing,mvp,passive-view,Java,Design Patterns,Swing,Mvp,Passive View,我试图在JavaSwingUI应用程序中遵循MVP(特别是被动视图)模式 应用程序的基本设计是一个向导控件。屏幕分为两个主要部分: 活动视图 带有导航按钮的静态导航栏 用户可以使用按钮更改活动视图,但始终显示该栏 在对这个场景进行建模时,我有一组不同的screer,每个screer都有自己的演示者、视图接口和视图实现(使用JPanel)。然后,我有一个Shell演示器,使用JFrame查看intefrace和视图实现。其想法是,shell将首先加载,并且始终显示,显示底部导航栏,并为活动视图
- 活动视图
- 带有导航按钮的静态导航栏李>
interface View {
}
class Presenter {
View view;
public Presenter(View view) {
this.view = view;
}
public View getView() {
return view;
}
}
interface ShellView extends View {
void setActiveView(View activeView);
}
class ShellPresenter extends Presenter {
private ShellView shellView;
public void setActivePresenter(Presenter activePresenter) {
shellView.setActiveView(activePresenter.getView());
}
}
class ShellFrame implements ShellView {
private JFrame frame;
private JPanel activePanel;
private JPanel navigationBar;
public ShellFrame() {
Container c = frame.getContentPane();
c.add(activePanel);
c.add(navigationBar);
}
public setActiveView(View activeView) {
???
}
}
class PresenterManager {
private Presenter activePresenter;
private List<Presenter> allPresenters;
IView view;
PresenterManager(IView view) {
this.view = view;
view.subscribe(this);
}
void addPresenter(Presenter p) {
allPresenters.add(p);
}
void setView(int index) {
view.setView(index);
activePresenter = allPresenters.get(index);
}
}
class SwingView implements IView {
List<SubView> allViews;
SubView activeView;
int lastIndex;
public void setView(int index) {
if(index != lastIndex) {
activeView.setVisible(false);
activeView = allViews.get(index);
lastIndex = index;
}
}
}
问题在于setActiveView方法:我不确定如何将activeView设置为activePanel,因为视图接口是通用的,因此对JPanels一无所知。显然,我不想让我的演示者也知道JPanels。能否将视图的定义修改为:
interface View {
JComponent getContainer();
}
以便每个视图都可以轻松获取视图内容?shell不需要知道返回的是JComponent的什么实现。您的视图界面需要提供某种方式来获取可在JPanel中显示的内容:
interface View {
Component getComponent();
}
然后在ShellFrame中(假设您像我一样使用BorderLayout),可以按以下方式设置视图:
public setActiveView(View activeView) {
activePanel.add(activeView.getComponent(), BorderLayout.CENTER);
}
问题是您的
JFrame
是视图,而不是每个单独的活动子视图。当前处于活动状态的视图是渲染作业,因此应该由视图
执行,而不是由演示者
执行。想象一下,您想在不同的视图中交换,它们不是只有一个子视图可见,而是全部可见,但处于活动状态的子视图具有不同的背景颜色。演示者只控制哪个是活动的,而视图
控制活动的含义
因此,如果不破坏封装,您的任务就无法完成,因为您正试图完成一项本质上破坏封装的工作。所以我会这样做:
interface View {
}
class Presenter {
View view;
public Presenter(View view) {
this.view = view;
}
public View getView() {
return view;
}
}
interface ShellView extends View {
void setActiveView(View activeView);
}
class ShellPresenter extends Presenter {
private ShellView shellView;
public void setActivePresenter(Presenter activePresenter) {
shellView.setActiveView(activePresenter.getView());
}
}
class ShellFrame implements ShellView {
private JFrame frame;
private JPanel activePanel;
private JPanel navigationBar;
public ShellFrame() {
Container c = frame.getContentPane();
c.add(activePanel);
c.add(navigationBar);
}
public setActiveView(View activeView) {
???
}
}
class PresenterManager {
private Presenter activePresenter;
private List<Presenter> allPresenters;
IView view;
PresenterManager(IView view) {
this.view = view;
view.subscribe(this);
}
void addPresenter(Presenter p) {
allPresenters.add(p);
}
void setView(int index) {
view.setView(index);
activePresenter = allPresenters.get(index);
}
}
class SwingView implements IView {
List<SubView> allViews;
SubView activeView;
int lastIndex;
public void setView(int index) {
if(index != lastIndex) {
activeView.setVisible(false);
activeView = allViews.get(index);
lastIndex = index;
}
}
}
类PresenterManager{
私人演讲者主动演讲者;
所有演讲者的私人名单;
IView视图;
PresenterManager(IView视图){
this.view=视图;
查看。订阅(本);
}
void addPresenter(Presenter p){
所有演示者。添加(p);
}
void setView(int索引){
view.setView(索引);
activePresenter=allPresenters.get(索引);
}
}
类SwingView实现IView{
列出所有视图;
子视图activeView;
int-lastIndex;
公共void集合视图(int索引){
如果(索引!=lastIndex){
activeView.setVisible(false);
activeView=allViews.get(索引);
lastIndex=指数;
}
}
}
你知道怎么做吗?这些答案都不是特别好。我刚刚发布了以下帖子: