做Swing桌面程序,该怎样将组件与业务逻辑分离?

做Swing桌面程序,该怎样将组件与业务逻辑分离?,第1张

这是一个问题。因为没有深入学习过这方面的知识,所以自己也没有想过如何能实现这种分离。 今天有个朋友用Swing做了一个小的桌面程序,是一个简单的管理系统。代码很复杂,主要是写的很复杂,没有逻辑和层次感,到处是组件,到处是判断,每追加一个功能,代码就要翻来翻去找很久。 于是今天晚上自己闲来无事,简单的写了一些代码,看是否可以将组件与业务逻辑分离开呢? 如果大侠看到了不要见笑啊~ 首先,我要的是一个登录界面,界面很简单,上面留一个JLabel的位置,输出错误提示信息用。然后下面就是 用户名和密码 的输入框。见下图: 待用户输入用户名和密码后,点击登录按钮,根据用户名和密码进行验证。如果用户名和密码为空,则报错。如果填写了用户名和密码,则认为登录成功,由于只是演示,就没有真正的去实现如何验证。 现在代码的结构是这样的。|--com |--bzwm |--testp |--common |--event |--frame |--listener 如上图,主要由4个包。common包,放一些通用的类,可以有一些工具类等等。这次我将EventMgr.java放在common包下,用来管理事件。 event包,放入每个动作的event,我先定义了一个抽象类BaseEvent.java然后是本次要实现的功能的事件:LogonEvent.java frame包,是一些画面的实现类。本次登录用的LoadFrame.java放在这个包下。 listener包,是放具体的业务逻辑实现类的。首先定义接口 IListener.java画面实现 IListener 接口,方便回调回主画面,方便根据业务逻辑处理结果来重画组件。然后定义接口 IService.java业务逻辑类要实现 IService 接口,我在这个接口中定义了两个方法,第一个方法,检查用户的输入数据是否正确,或者说 *** 作是否正确,第二个方法,根据用户的输入和事件,来完成业务逻辑处理。本次登录用的逻辑类 LogonService.java 实现了IService 接口。 好,结构介绍完了,来看代码。1.IListener.javapackage com.bzwm.testp.listenerimport com.bzwm.testp.event.BaseEvent/** * @author bzwm * */ public interface IListener { /** * 处理事件结束 * 这里将回调到画面上,方便对画面进行重画 * @param event */ public void eventCompleted(BaseEvent event)} 2.IService.javapackage com.bzwm.testp.listenerimport com.bzwm.testp.event.BaseEvent/** * @author bzwm * */ public interface IService { /** * 开始处理事件 * 对用户的输入, *** 作做初步的检查,如果检查失败,则没有必要继续向下进行 * @param event */ public void eventStarted(BaseEvent event)/** * 处理事件 * 进行一些逻辑处理 * 得到单纯的数据,不用考虑画面上的组件 * @param event */ public void service(BaseEvent event)} 3.LoadFrame.java主画面,程序的入口,实现了IListener接口package com.bzwm.testp.frameimport com.bzwm.testp.common.EventMgrimport com.bzwm.testp.event.BaseEventimport com.bzwm.testp.event.LogonEventimport com.bzwm.testp.listener.IListenerimport com.bzwm.testp.listener.LogonServiceimport java.awt.BorderLayoutimport java.awt.Colorimport java.awt.FlowLayoutimport java.awt.event.ActionEventimport java.awt.event.ActionListenerimport javax.swing.JButtonimport javax.swing.JFrameimport javax.swing.JLabelimport javax.swing.JPanelimport javax.swing.JPasswordFieldimport javax.swing.JTextField/** * @author bzwm * */ public class LoadFrame extends JFrame implements IListener { /** 标题:用户ID */ private JLabel userIdLbl = null/** 输入框:用户ID */ private JTextField userIdTxt = null/** 标题:密码 */ private JLabel passwordLbl = null/** 输入框:密码 */ private JPasswordField passwordTxt = null/** 登录按钮 */ private JButton logonBtn = null/** 重置按钮 */ private JButton resetBtn = null/** 新用户注册按钮 */ private JButton registerBtn = null/** 错误提示信息 */ private JLabel errorLbl = nullEventMgr mrg = null/** * 构造方法 * * @param title * 标题 */ public LoadFrame(String title) { super(title)initComponents()layoutComponents()mrg = new EventMgr()// 追加监听器 mrg.addListener(this)mrg.addService(new LogonService())} /** * 对组件进行初始化 * */ private void initComponents() { userIdLbl = new JLabel("用户名")userIdTxt = new JTextField(10)passwordLbl = new JLabel("密码")passwordTxt = new JPasswordField(10)logonBtn = new JButton("登录")resetBtn = new JButton("重置")registerBtn = new JButton("注册")errorLbl = new JLabel()errorLbl.setForeground(Color.RED)} /** * 进行布局,给组件添加事件监听 * */ private void layoutComponents() { JPanel topPnl = new JPanel()topPnl.add(errorLbl)JPanel mainPnl = new JPanel(new BorderLayout())JPanel inputPnl = new JPanel(new java.awt.GridLayout(2, 2, 2, 2))inputPnl.add(userIdLbl)inputPnl.add(userIdTxt)inputPnl.add(passwordLbl)inputPnl.add(passwordTxt)inputPnl.setSize(280, 100)mainPnl.add(inputPnl, BorderLayout.NORTH)JPanel footPnl = new JPanel(new FlowLayout(FlowLayout.RIGHT))logonBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { logonBtnClick()} })resetBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { resetBtnClick()} })registerBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { regBtnClick()} })footPnl.add(logonBtn)footPnl.add(resetBtn)footPnl.add(registerBtn)mainPnl.add(footPnl, BorderLayout.SOUTH)this.add(topPnl, BorderLayout.NORTH)this.add(mainPnl, BorderLayout.CENTER)this.setLocation(200, 200)this.setSize(300, 300)this.setVisible(true)this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)} /** * */ private void logonBtnClick() { new Thread() { public void run() { mrg.dispatch(new LogonEvent(userIdTxt.getText(), passwordTxt.getText()))} }.start()} /** * */ private void resetBtnClick() { userIdTxt.setText("")passwordTxt.setText("")} /** * */ private void regBtnClick() { } /* * (non-Javadoc) * * @see com.bzwm.testp.listener.IListener#eventCompleted(com.bzwm.testp.event.BaseEvent) */ public void eventCompleted(BaseEvent event) { String error = event.getError()if (error.equals("")) { errorLbl.setText("登录成功")} else { errorLbl.setText(error)} } public static void main(String args[]) { new LoadFrame("LogonFrame")} }4.LogonService.java登录事件的逻辑处理类实现了IService接口package com.bzwm.testp.listenerimport com.bzwm.testp.event.BaseEventimport com.bzwm.testp.event.LogonEvent/** * @author bzwm * */ public class LogonService implements IService { /* * (non-Javadoc) * * @see com.bzwm.testp.listener.IService#eventStarted(com.bzwm.testp.event.BaseEvent) */ public void eventStarted(BaseEvent event) { LogonEvent logonEvent = (LogonEvent) eventString id = logonEvent.getId()String password = logonEvent.getPassword()// 对用户的输入进行初步check if (id == null || "".equals(id)) { event.setError("用户名为空")} if (password == null || "".equals(password)) { event.setError("密码为空")} } /* * (non-Javadoc) * * @see com.bzwm.testp.listener.IService#service(com.bzwm.testp.event.BaseEvent) */ public void service(BaseEvent event) { if (!event.isError()) { LogonEvent logonEvent = (LogonEvent) event// 用户id和密码已经经过的初步check,现在去登录,检查是否已经注册 logon(logonEvent)// 这里停顿秒,算是去服务器验证了 try { Thread.sleep(5000)} catch (InterruptedException e) { e.printStackTrace()} } } private void logon(LogonEvent e) { // 验证DB,用户ID是否存在,密码是否正确 // 如果不存在,则setError(),密码不正确,setError() // ... } }5.EventMgr.java管理事件package com.bzwm.testp.commonimport com.bzwm.testp.event.BaseEventimport com.bzwm.testp.listener.IListenerimport com.bzwm.testp.listener.IServiceimport java.util.ArrayListimport java.util.List/** * @author bzwm * */ public class EventMgr { /** 回调回主画面的监听集合 */ private List<IListener>listeners = new ArrayList<IListener>()/** 业务逻辑的监听集合 */ private List<IService>services = new ArrayList<IService>()/** * * @param event */ public void dispatch(BaseEvent event) { fireEventStarted(event)fireEventService(event)fireEventCompleted(event)} /** * * @param listener */ public void addListener(IListener listener) { listeners.add(listener)} /** * * @param listener */ public void removeListener(IListener listener) { listeners.remove(listener)} /** * * @param service */ public void addService(IService service) { services.add(service)} /** * * @param service */ public void removeService(IService service) { services.remove(service)} /** * * @param event */ private void fireEventStarted(BaseEvent event) { for (IService service : services) { service.eventStarted(event)} } /** * * @param event */ private void fireEventService(BaseEvent event) { for (IService service : services) { service.service(event)} } /** * * @param event */ private void fireEventCompleted(BaseEvent event) { for (IListener listener : listeners) { listener.eventCompleted(event)} } }6.BaseEvent.java抽象类,抽象的事件这其中的设计还很有待商榷package com.bzwm.testp.event/** * @author bzwm * */ public abstract class BaseEvent { /** * 处理过程中的错误信息 这里可以选择自定义一个Error类来完成 由于只是示范,就不写了 另外,这种保存error信息的方法确实很笨 */ private String error = ""/** * 保存处理返回的结果 这里可以自定义一个Data来管理 由于是示范,也就不写了 用一个Object返回处理结果,有很多局限性 */ private Object result = null/** * @return the result */ public Object getResult() { return result} /** * @param result * the result to set */ public void setResult(Object result) { this.result = result} /** * @return the error */ public String getError() { return error} /** * @param error * the error to set */ public void setError(String error) { this.error = this.error + " " + error} public boolean isError() { return !error.equals("")} }7.LogonEvent.java用户登录事件package com.bzwm.testp.event/** * @author bzwm * */ public class LogonEvent extends BaseEvent { /** 用户ID */ private String id = null/** 密码 */ private String password = nullpublic LogonEvent(String i, String p) { setId(i)setPassword(p)} /** * @return the id */ public String getId() { return id} /** * @param id * the id to set */ public void setId(String id) { this.id = id} /** * @return the password */ public String getPassword() { return password} /** * @param password * the password to set */ public void setPassword(String password) { this.password = password} } 根据上述代码,基本功能完成了。 也许会感觉为这一点功能写这么多类不值得,但代码会清晰一点,虽然设计上,比如类的构造上还不够合理,我也没思考太多,想到这些就写出来了。 不过这样还有一个好处,比如说,你想给登录事件加输出log的功能,那么比较简单,只要写一个类,实现了IService即可。(因为log写在本地文件里,所以不用回调回主画面)然后在LoadFrame.java中的构造方法改一下就OK了。下面是输出log用的service 8.LogService.javapackage com.bzwm.testp.listenerimport com.bzwm.testp.event.BaseEventimport com.bzwm.testp.event.LogonEvent/** * @author bzwm * 关于输出log类的设计,还可以改进,比如LogService可以是个抽象类,下面是具体的LogonLogService, * 在父类中做一些共同的 *** 作,比如IO *** 作等。 * 因为很多 *** 作都要有log,可以试着给每个画面定义一个输出log的类, * 专门来管理log信息。 * 这里为简单起见,也就不做那么多了,并且只将信息打印在控制台。 */ public class LogService implements IService { /* * (non-Javadoc) * * @see com.bzwm.testp.listener.IService#eventStarted(com.bzwm.testp.event.BaseEvent) */ public void eventStarted(BaseEvent event) { // TODO Auto-generated method stub if (event instanceof LogonEvent) { LogonEvent e = (LogonEvent) eventSystem.out.println(e.getId() + " 准备登录了")} } /* * (non-Javadoc) * * @see com.bzwm.testp.listener.IService#service(com.bzwm.testp.event.BaseEvent) */ public void service(BaseEvent event) { // TODO Auto-generated method stub if (event instanceof LogonEvent) { LogonEvent e = (LogonEvent) eventString error = e.getError()if (error.equals("")) { System.out.println(e.getId() + " 登录了")} else { System.out.println(e.getId() + " 登录失败了 " + error)} } } }接着,改 LoadFrame.java类。只写出改的部分,它的构造方法: public LoadFrame(String title) { super(title)initComponents()layoutComponents()mrg = new EventMgr()// 追加监听器 mrg.addListener(this)mrg.addService(new LogonService())mrg.addService(new LogService())}这样,把代码拷贝下来,重新运行下,就出现log了。 这只是登录的功能,如果还要完成注册的功能,则还是一样的步骤,写一个Dialog类,继承JDialog,实现IListener接口,定义一个RegEvent.java继承BaseEvent.java,写一个RegService类,实现IService接口,总之把相应包下面,加入自己的实现,然后将监听还是注册到EventMgr里就可以实现了。 好了。欢迎交流,谢谢!

1、24M的内存在Java Swing程序里算是比较正常的。2、关闭一个Tab后,这个Tab上所使用的对象你销毁了么?如果销毁了,那么你要等到JVM进行垃圾回收的时候才能看到内存减少(一般会在heap容量不够的时候才会执行)。一个简单的验证方法是,你关闭该tab之后再次打开,内存如果没有增多,说明是正常的。3、在Java中,除非涉及到流 *** 作,否则很难写出来一个memory leak的程序......如果不放心可以使用jprofiler来检测一下JVM,看看你创建的对象是不是过多。

swing的意思:

v.(使)摆动,摇摆,摇荡;纵身跃向;荡向;悬吊到;(使)弧线运动,转弯,转动。

n.摆动;挥动;转动;强劲节奏;改变;改变的程度;秋千。

1、读音:英 [swɪŋ],美 [swɪŋ]。

2、固定搭配:

The Swing 秋千 裁缝 摇摆乐 全挥杆教学。

Swing Shift 小迷糊的情泪 小夜班 中班 小迷糊情泪。

Full swing 如火如荼 高挥杆 全力挥拍 达到活动的高潮。

Swing Copters 摇摆直升机 摇摇欲坠 晃飞机 旋转直升机。

3、例句:

I like to swing.

我喜欢荡秋千。                                         

扩展资料 

swing的过去式:swung,词汇解释如下:

1、释义:

v.(使)摆动,摇摆,摇荡;纵身跃向;荡向;悬吊到;(使)弧线运动,转弯,转动。

2、读音:英 [swʌŋ],美 [swʌŋ]。

3、例句:

The door swung open again, spilling light into the cell.

门再次打开了,光照亮了小屋。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11306878.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存