请注意,这是一篇很长的文章。很抱歉,但我想阐明我的观点:
很长一段时间以来,我一直在想如何将 Swing GUI 与表示和业务逻辑分开。 在工作中,我必须为一些数据实现 3 MD Excel 导出,并使用一个小的 Swing 对话框来配置导出。 我们没有为此使用像 Spring 这样的框架,所以我必须自己实现它。
我想将 GUI 与业务逻辑完全分开,它们的任务如下:
- 告诉 BL 从 GUI 开始工作
- 从 BL 到 GUI 报告进度
- 报告从 BL 到 GUI 的日志记录
- 将 BL 结果委托(delegate)给 GUI
当然,GUI 不应该注意到 BL 的实现,反之亦然。
我为上面的所有这些任务创建了几个接口(interface),e。 G。一个 ProgressListener
,LogMessageListener
,JobDoneListener
,
等等,由业务逻辑触发。例如,如果业务逻辑想要讲述日志记录,它会调用
fireLogListeners("Job has been started");
实现公共(public)接口(interface) LogListener + 的类附加到 BL,现在将通知“作业已启动”日志消息。 所有这些监听器此时都由 GUI 本身实现,通常看起来像这样:
public class ExportDialog extends JDialog implements ProgressListener, LogListener, JobFinishedListener, ErrorListener {
@Override
public void jobFinished(Object result){
// Create Save File dialog and save exported Data to file.
}
@Override
public void reportProgress(int steps){
progressBar.setValue(progressBar.getValue()+steps);
}
@Override
public void errorOccured(Exception ex, String additionalMessage){
ExceptionDialog dialog = new ExceptionDialog(additionalMessage, ex);
dialog.open();
}
// etc.
}
“GUI 和 BL 创建类”只是将 GUI(作为所有这些监听器的界面)附加到 BL,看起来像这样:
exportJob.addProgressListener(uiDialog);
exportJob.addLogListener(uiDialog);
exportJob.addJobFinishedListener(uiDialog);
exportJob.start();
我现在对此非常不确定,因为它看起来很奇怪,因为所有这些新创建的监听器接口(interface)。 你有什么想法? 如何将 Swing GUI 组件与 BL 分开?
编辑: 为了更好地演示,我在 eclipse file-upload.net/download-9065013/exampleWorkspace.zip.html 中创建了一个演示工作区 我也将它粘贴到 pastebin,但最好在 eclipse 中导入这些类,相当多的代码 http://pastebin.com/LR51UmMp
最佳答案
一些事情。
我不会在 ExportFunction 类中包含 uiDialog 代码。整个执行方法应该只是主类中的代码。 ExportFunctions 的责任是“导出”而不是“显示 gui”。
public static void main(String[] args) {
ExportFunction exporter = new ExportFunction();
final ExportUIDialog uiDialog = new ExportUIDialog();
uiDialog.addActionPerformedListener(exporter);
uiDialog.pack();
uiDialog.setVisible(true);
}
(不需要 Swing.invokeLater())
您似乎设计过度了。我不知道为什么您会期望同时运行多个线程。当您按下按钮时,您只会期望一个线程运行,对吗?那么就不需要 actionPerformedListener 数组了。
而不是这个:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (startConditionsFulfilled()) {
fireActionListener(ActionPerformedListener.STARTJOB);
}
}
});
为什么不只是:
final ExportJob exportJob = new ExportJob();
exportJob.addJobFinishedListener(this);
exportJob.addLogListener(this);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exportJob.start();
}
});
这样您就可以摆脱实际上没有任何作用的 ExportFunction。
您似乎有很多听众数组。除非你真的真的需要它们,否则我不会为它们操心,并尽可能简单。
代替:
Thread.sleep(1000);
fireLogListener("Excel Sheet 2 created");
Thread.sleep(1000);
只需:
Thread.sleep(1000);
log("Excelt Sheet 1 created");
Thread.sleep(1000);
日志在哪里:
private void log(final String message) {
((DefaultListModel<String>) list.getModel()).addElement(message);
}
通过这种方式,您可以使它更简单、更清晰。
GUI 不应该知道 BL,但 BL 必须以某种方式告诉 GUI 做什么。您可以无限地抽象出许多接口(interface),但在 99.99% 的应用程序中,这不是必需的,尤其是您的应用程序,它看起来相当简单。
因此,虽然您编写的代码非常好,但我会尝试简化和减少接口(interface)。它不需要那么多工程。
关于java - 不使用Spring等时如何将Swing GUI与业务逻辑分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24228513/