简体   繁体   English

在Java Swing中将域与用户界面分开

[英]Separate user interface from domain in java Swing

As a Java Swing newbie, I have some trouble separating the user interface logic from the domain logic. 作为Java Swing的新手,我在将用户界面逻辑与域逻辑分离时遇到了一些麻烦。

I have a small (trivial?) Swing app with a JFrame that contains a JLabel, JTextField and a JButton. 我有一个小的(琐碎的?)Swing应用程序,其中包含一个JLrame,包含一个JLabel,JTextField和一个JButton。 When pressing the JButton a JFileChooser dialog pops up. 按下JButton时会弹出一个JFileChooser对话框。 After selecting a file, the JTextField contains the absolute path to the file. 选择文件后,JTextField包含文件的绝对路径。 Nothing spectaculair so far. 到目前为止还没有什么壮观的景象。 The next thing I want to accomplish is that this absolute path of the file is 'injected' into a file manager class that will handle the actual processing of the file when the selection is made and the JTextField is updated (each time a file is selected using the JButton). 接下来我想要完成的是将文件的绝对路径“注入”文件管理器类,该类将在进行选择并更新JTextField时处理文件的实际处理(每次选择文件时)使用JButton)。

Questions I have: 我有的问题:

  1. How do I let the file manager know when to start reading the file? 如何让文件管理器知道何时开始读取文件? (for example count the number of lines within that file) (例如,计算该文件中的行数)
  2. How can I implement the domain layer in such a way that minimal information is shared within the UI layer? 如何以在UI层中共享最少信息的方式实现域层? Should I add a filemanager instance to the UI? 我应该在UI中添加filemanager实例吗?
  3. Should I use the value of the JTextField as the reference towards the file manager, or should I use the JButton action to set the value into the file manager? 我应该使用JTextField的值作为文件管理器的引用,还是应该使用JButton操作将值设置到文件管理器中? What I mean by that is: use propertychangelistener of JTextField OR use actionlistener of JButton? 我的意思是:使用JTextField的propertychangelistener或使用JButton的actionlistener?
  4. Should I use a filebean to store the absolute path of the file within the domain layer or just directly insert it to the file manager? 我应该使用filebean来存储域层中文件的绝对路径,还是直接将其插入文件管理器? The difference is: when I use a property change listener the value of the absolute file path can be updated when the UI input changes, but when I insert the value directly using a contructor or setter, I have to handle the change in the file manager instead of handle the change in the filebean. 不同之处在于:当我使用属性更改侦听器时,可以在UI输入更改时更新绝对文件路径的值,但是当我使用构造函数或setter直接插入值时,我必须处理文件管理器中的更改而不是处理filebean中的更改。
  5. How can I reference the filebean that is used in the UI within the file manager within the domain logic? 如何在域逻辑中引用文件管理器中UI中使用的filebean?
  6. Is the domain logic the same as the business logic? 域逻辑是否与业务逻辑相同? I mean: file manager class should be in package whatever.b-logic and filebean class should be in package whatever.domain?? 我的意思是:文件管理器类应该在包中的what.b-logic和filebean类应该在包中的whatever.domain ??

The application is divided into several packages: 该应用程序分为几个包:

  • whatever : main class 无论如何:主要阶级
  • whatever.presentation : swing stuff 无论如何:摇摆的东西
  • whatever.domain : data stuff whatever.domain:数据的东西
  • whatever.logic : application logic whatever.logic:应用程序逻辑

I hope I am clear enough... 我希望我足够清楚......

Thanks in advance for clearing things up. 提前谢谢清理。

Personally, when I approach these kind of problems I try and look at re-usability and responsibility (who's responsible for what) as primary requirements. 就个人而言,当我处理这些问题时,我会尝试将可重用性和责任(谁负责什么)视为主要要求。

That is, I try and get my models set up in such away so that they don't care about how or where the data is coming from or going to, they simple provide the interface access to make it happen. 也就是说,我尝试让我的模型设置在这样的位置,这样他们就不关心数据来自或去往的方式和位置,它们简单地提供了接口访问以实现它。

To connect all the elements to together, I rely on the model providing events back to the client, cause the model shouldn't care about who wants to know, just provide the required functionality. 要将所有元素连接在一起,我依靠模型将事件提供给客户端,因为模型不应该关心谁想知道,只需提供所需的功能。 So, in order to provide feedback to the client, I'd rely on a series of listeners. 所以,为了向客户提供反馈,我依靠一系列的听众。

I would break the listeners down into specific jobs, such notification of the file reading would be it's own listener, changes to the model (adding/removing/updating) the file beans would be another. 我会将监听器分解为特定的工作,例如文件读取的通知将是它自己的监听器,对模型的更改(添加/删除/更新)文件bean将是另一个。 Other notifications would be require different listeners, this stops you from creating monster listeners for which implementations don't really want to know about. 其他通知将需要不同的侦听器,这将阻止您创建实现并不真正想要了解的怪物侦听器。

For setting values in the model, I would err on the side of property setters/getters. 为了在模型中设置值,我会在属性设置器/ getter一侧犯错。 This decouples your model from the implementation (what if you are using the model in an automated fashion??) 这会将您的模型与实现分离(如果您以自动方式使用模型,该怎么办?)

Internal data would be best managed by the model if possible. 如果可能,内部数据最好由模型管理。 That is, if you change a property on a file bean that the model is managing, the model should be capable of monitoring the change and dealing with it. 也就是说,如果更改模型正在管理的文件bean上的属性,则模型应该能够监视更改并处理它。 Having said that, you may want a dumb model at some time in the future, where you could batch update a series of file beans and then ask the model to update itself. 话虽如此,您可能在将来的某个时间想要一个愚蠢的模型,您可以批量更新一系列文件bean,然后让模型自行更新。

I, personally, would probably provide the means for the model to be updated externally while providing at least one implementation capable of providing self monitoring, this gives you flexibility to chose the right model for the right situation. 我个人可能会提供模型在外部更新的方法,同时提供至少一个能够提供自我监控的实现,这使您可以灵活地为正确的情况选择正确的模型。

There is also the danger of memory leaks here. 此处还存在内存泄漏的危险。 If you don't properly remove any listeners from the file bean when you no longer need them, you could end up preventing the bean from been garbage collected at a later time. 如果在不再需要文件bean时没有从文件bean中正确删除任何侦听器,最终可能会阻止该bean在以后被垃圾回收。

Where possible, work with interfaces. 尽可能使用接口。 This provides an great deal of flexibility when trying to pull these models together. 在尝试将这些模型组合在一起时,这提供了很大的灵活性。

For what you describe, I would allow the file bean to be the responsibility of the file manager, such that the file manager becomes a container of file beans. 对于您所描述的内容,我将允许文件管理器负责文件管理器,以便文件管理器成为文件bean的容器。

Depending on how large your project is and how you might want to reuse the code in the future will greatly effect the layout of the code. 根据项目的大小以及将来如何重用代码将极大地影响代码的布局。

I usually put UI code in a UI package and sub packages, but that's just me. 我通常把UI代码放在UI包和子包中,但那只是我。 I tend to separate interface content from implementation content (usually physically in separate Jar files, but again, that's me). 我倾向于将界面内容与实现内容分开(通常在物理上在单独的Jar文件中,但同样,那就是我)。 This means that I only need to include the interface library and what ever implementation I might be using, using a factory of some sort to actually instantiate the implementation if required (or directly as is required). 这意味着我只需要包含接口库以及我可能正在使用的实现,使用某种工厂来实际实例化实现(如果需要)(或直接根据需要)。 Think JDBC driver for example. 以JDBC驱动程序为例。

You want to look towards sphere's of responsibility. 你想看看球体的责任。 From what you describe, I feel that the file bean falls in the file manager's sphere of responsibility so I would bind the two together. 根据您的描述,我觉得文件bean属于文件管理器的责任范围,因此我将两者绑定在一起。

That's just my point of view 这只是我的观点

Here are a few suggestions: 以下是一些建议:

  • Use SwingWorker , illustrated here , to keep the GUI lively while listening for progress. 使用这里所示的SwingWorker ,在监听进度的同时保持GUI的活泼。

  • Use Action , illustrated here , to encapsulate functionality. 使用此处说明的Action来封装功能。

  • Use File , a convenient, cross-platform abstraction. 使用File ,一种方便的跨平台抽象。 Use it to compose new abstractions, rather than pulling out non-cross-platform pieces. 使用它来构建新的抽象,而不是拉出非跨平台的部分。

Addendum: See also A Swing Architecture Overview and the answer . 附录:另请参阅Swing架构概述答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM