请注意,这是一篇很长的帖子。对不起,但我想澄清一点:
我想知道如何在很长一段时间内将Swing GUI与Presentation和Business Logic分开。 在工作中,我必须使用一个小的Swing对话框为一些数据实现3 MD Excel Export以配置导出。 我们不使用像Spring这样的框架,所以我必须自己实现它。
我想完全将GUI与Business Logic分开,后者正在执行精确的后续任务:
ProgressListener
,LogMessageListener
,JobDoneListener
,
等等,由Business Logic解雇。例如,如果业务逻辑想要告知记录,则调用
fireLogListeners("Job has been started");
实现公共接口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();
我现在对此非常不确定,因为它看起来很奇怪,因为所有新创建的侦听器接口。 你有什么想法? 如何将Swing GUI组件与BL分开?
修改 为了更好的演示目的,我在eclipse中创建了一个Demo工作区file-upload.net/download-9065013/exampleWorkspace.zip.html 我也把它粘贴到了pastebin,但最好在eclipse中导入这些类,相当多的代码http://pastebin.com/LR51UmMp
答案 0 :(得分:2)
一些事情。
我在ExportFunction类中没有uiDialog代码。整个执行方法应该只是主类中的代码。 ExportFunctions的责任是'导出'而不是'show 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);
其中log为:
private void log(final String message) {
((DefaultListModel<String>) list.getModel()).addElement(message);
}
这样你就可以保持简单和清洁。
GUI不应该知道BL,但BL不知何故必须告诉GUI该做什么。您可以使用大量接口抽象无限制,但在99.99%的应用程序中,这不是必需的,尤其是您的应用程序看起来相当简单。
因此,虽然您编写的代码非常好,但我会尝试简化并减少接口。它不能保证那么多工程。
答案 1 :(得分:2)
基本上,您的架构对我来说似乎没问题。我想你是否想知道是不是因为你设置了众多的听众。
解决方法可能是:
a)拥有一个通用的Event类,其中包含特定事件的子类。 您可以使用访问者来实现实际的侦听器。
b)使用事件总线(例如,参见番石榴)。 使用事件总线体系结构,您的模型将事件发布到事件总线, 您的UI对象将侦听事件总线中的事件,并对其进行过滤。
有些系统甚至可以使用注释来声明侦听器方法。