将MVC模式应用于现有应用程序

This is a follow up question to The MVC pattern and SWING. I am trying to implement the MVC pattern in an existing piece of code. The existing code creates a JFrame which acts as both the view and the controller. The JFrame has a table, and the table's model is an adapter to a custom data model. Whenever the user performs an action, the model would be updated by doing something like the following:

CustomDataTableModel cdtm = (CustomDataTableModel) DataTable.getModel();
CustomDataModel cdm = cdtm.getModel();
cdm.delete(1);

I've tried to visualise how it currently works, but I've also visualised how I imagine the relationships with the future controller and model should be.

MVC

Now, my question is simply whether I can continue using the model as it is now? Could I implement the following and still "adhere" to the MVC pattern?

  1. The user selects an element in the table, and clicks on a delete button.
  2. The view delegates the action to the controller.
  3. The controller access the table through an accessor on the view, and performs the update.
  4. The model, when it is updated, notifies the JTable that it has been changed.

If any other components in the view displays data from the table, then this could be solved by registering listeners on the JTable's table model.

Update 1

I've been thinking about the existing code in light of the MVC pattern, and I've redrawn the relationships a little. The point is that the controller is the behaviour of the view, thus the controller updates the model when users do stuff, and the view listens for changes in the model. However, nothing in the MVC pattern stops the view from listening to the model through a tablemodel - right?

MVC

Now, the user clicks the add button. The view notifies the controller that the add button has been clicked, and the controller takes care of creating a new item by invoking some method on the model. The view is registered as a listener on the model (through a table model) and updates its view. The controller may also be a listener on the model in case it needs to take care of disabling or locking fields. Have I not achieved what the MVC is all about; separation of concerns? As far as I can see, I've even introduced the adapter pattern to decouple the view even more from the model? It is late and I am tired, so that might be why it makes sense :-)

#0

In the general sense, I would advise you the following:

  • take a look at JGoodies Binding, it is not MVC but uses the "PresentationModel" pattern which is, in my opinion, better adapted to a whole application than MVC (which I find suitable for individual widgets only). This should solve your problem between your Domanin Model and the TableModel
  • if your application has only tables, then GlazedLists also makes a lot of sense: it will also isolate your Domain Model from your TableModel (but it doesn't enforce any global pattern, MVC or PM)

Regarding the current design you show, I would rather suggest that the View asks the Controller for an Action that the View will assign to the Delete button. Then the Controller can act on the Domain Model.

#1

That gets messy and confusing fast, alas, and the code base is already confusing due to lack of separation.

I suggest instead migrating distinct components to a clean, simple MVC design. Such a component (which is currently a view, controller, and model all mixed up together) would then be separated in a clean fashion, however you will then have the difficulty of how to handle the controller and model? As a temporary workaround, you'll be forced to designate the owner view as the controller, so the owner arguably has more responsibility. I think that this is a suitable workaround, because you will eventually separate more and more components into an MVC design, and the views that are also controllers will eventually become refactored as well.

In other words:

  1. For a large application, identify a small component. (The low-hanging fruit).
  2. Identify what code effectively controls that component. This is probably another 'view' class in this case.
  3. Separate the component identified in step one into a clean design.
  4. Explicitly configure the owner (view) identified in step to as the controller for the newly refactored component.
  5. Repeat until there is clean separation between ALL views and controllers.

Be careful to ensure that the application is still working at the end of every 'step 4' above, otherwise, you'll find yourself in a mess that just gets longer and longer to fix. (Even if the end result is nice and clean, you may have missed your deadline).

Keep in mind that it may be difficult to extract the 'model' from the code at first - the controllers and views will be easiest to separate, but eventually, the models will become easier to separate as well. Whenever you manage to extract a model, write unit tests that test that model in isolation.

The presence of a well written suite of unit tests will help ensure that the application continues to have well-defined separation of concerns. (If concerns are not separated, then it becomes very hard to unit test), so the unit testing approach serves as a motivator.

I hope that makes sense.

推荐文章

mongoDB伪副本集集群搭建

mongoDB伪副本集集群搭建

推荐文章

如何检查桌子上的锁

如何检查桌子上的锁

推荐文章

5.常见概念和问题

5.常见概念和问题

推荐文章

909422229_在windows上安装redis并设置密码,IP绑定【提供安装包】

909422229_在windows上安装redis并设置密码,IP绑定【提供安装包】

推荐文章

rails中的link_to_remote出现问题

rails中的link_to_remote出现问题

推荐文章

redis 空格问题

redis 空格问题

推荐文章

什么是asp.net mvc的理想候选者

什么是asp.net mvc的理想候选者

推荐文章

MongoDB服务无法启动,windows提示发生服务特定错误:100

MongoDB服务无法启动,windows提示发生服务特定错误:100

推荐文章

一个.Net用户的源代码管理

一个.Net用户的源代码管理

推荐文章

从Winforms迁移到WPF

从Winforms迁移到WPF

推荐文章

关于redis有效期设置问题

关于redis有效期设置问题

推荐文章

QC++语法?

QC++语法?

推荐文章

如何为NSOutputStream添加数据?

如何为NSOutputStream添加数据?

推荐文章

Redis-codis集群3.0

Redis-codis集群3.0

推荐文章

数据存储---GreenPlum实践

数据存储---GreenPlum实践

推荐文章

设计模式不适用于Flex 4项目

设计模式不适用于Flex 4项目