做Swing傳統型程式,該怎樣將組件與商務邏輯分離?

來源:互聯網
上載者:User

做Swing傳統型程式,該怎樣將組件與商務邏輯分離?

這是一個問題。

因為沒有深入學習過這方面的知識,所以自己也沒有想過如何能實現這種分離。

 

今天有個朋友用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.java

package com.bzwm.testp.listener;</p><p>import com.bzwm.testp.event.BaseEvent;</p><p>/**<br /> * @author bzwm<br /> *<br /> */<br />public interface IListener {</p><p>/**<br /> * 處理事件結束<br /> * 這裡將回調到畫面上,方便對畫面進行重畫<br /> * @param event<br /> */<br />public void eventCompleted(BaseEvent event);<br />}

 

2.IService.java

package com.bzwm.testp.listener;</p><p>import com.bzwm.testp.event.BaseEvent;</p><p>/**<br /> * @author bzwm<br /> *<br /> */<br />public interface IService {<br />/**<br /> * 開始處理事件<br /> * 對使用者的輸入,操作做初步的檢查,如果檢查失敗,則沒有必要繼續向下進行<br /> * @param event<br /> */<br />public void eventStarted(BaseEvent event);</p><p>/**<br /> * 處理事件<br /> * 進行一些邏輯處理<br /> * 得到單純的資料,不用考慮畫面上的組件<br /> * @param event<br /> */<br />public void service(BaseEvent event);<br />}

 

3.LoadFrame.java

主畫面,程式的入口,實現了IListener介面

package com.bzwm.testp.frame;</p><p>import com.bzwm.testp.common.EventMgr;<br />import com.bzwm.testp.event.BaseEvent;<br />import com.bzwm.testp.event.LogonEvent;<br />import com.bzwm.testp.listener.IListener;<br />import com.bzwm.testp.listener.LogonService;<br />import java.awt.BorderLayout;<br />import java.awt.Color;<br />import java.awt.FlowLayout;<br />import java.awt.event.ActionEvent;<br />import java.awt.event.ActionListener;<br />import javax.swing.JButton;<br />import javax.swing.JFrame;<br />import javax.swing.JLabel;<br />import javax.swing.JPanel;<br />import javax.swing.JPasswordField;<br />import javax.swing.JTextField;</p><p>/**<br /> * @author bzwm<br /> *<br /> */<br />public class LoadFrame extends JFrame implements IListener {<br />/** 標題:使用者ID */<br />private JLabel userIdLbl = null;</p><p>/** 輸入框:使用者ID */<br />private JTextField userIdTxt = null;</p><p>/** 標題:密碼 */<br />private JLabel passwordLbl = null;</p><p>/** 輸入框:密碼 */<br />private JPasswordField passwordTxt = null;</p><p>/** 登入按鈕 */<br />private JButton logonBtn = null;</p><p>/** 重設按鈕 */<br />private JButton resetBtn = null;</p><p>/** 新使用者註冊按鈕 */<br />private JButton registerBtn = null;</p><p>/** 錯誤提示資訊 */<br />private JLabel errorLbl = null;</p><p>EventMgr mrg = null;</p><p>/**<br /> * 構造方法<br /> *<br /> * @param title<br /> * 標題<br /> */<br />public LoadFrame(String title) {<br />super(title);<br />initComponents();<br />layoutComponents();<br />mrg = new EventMgr();<br />// 追加監聽器<br />mrg.addListener(this);<br />mrg.addService(new LogonService());<br />}</p><p>/**<br /> * 對組件進行初始化<br /> *<br /> */<br />private void initComponents() {<br />userIdLbl = new JLabel("使用者名稱");<br />userIdTxt = new JTextField(10);</p><p>passwordLbl = new JLabel("密碼");<br />passwordTxt = new JPasswordField(10);</p><p>logonBtn = new JButton("登入");<br />resetBtn = new JButton("重設");<br />registerBtn = new JButton("註冊");</p><p>errorLbl = new JLabel();<br />errorLbl.setForeground(Color.RED);<br />}</p><p>/**<br /> * 進行布局,給組件添加事件監聽<br /> *<br /> */<br />private void layoutComponents() {<br />JPanel topPnl = new JPanel();<br />topPnl.add(errorLbl);</p><p>JPanel mainPnl = new JPanel(new BorderLayout());<br />JPanel inputPnl = new JPanel(new java.awt.GridLayout(2, 2, 2, 2));<br />inputPnl.add(userIdLbl);<br />inputPnl.add(userIdTxt);<br />inputPnl.add(passwordLbl);<br />inputPnl.add(passwordTxt);<br />inputPnl.setSize(280, 100);<br />mainPnl.add(inputPnl, BorderLayout.NORTH);</p><p>JPanel footPnl = new JPanel(new FlowLayout(FlowLayout.RIGHT));<br />logonBtn.addActionListener(new ActionListener() {<br />public void actionPerformed(ActionEvent e) {<br />logonBtnClick();<br />}<br />});<br />resetBtn.addActionListener(new ActionListener() {<br />public void actionPerformed(ActionEvent e) {<br />resetBtnClick();<br />}<br />});</p><p>registerBtn.addActionListener(new ActionListener() {<br />public void actionPerformed(ActionEvent e) {<br />regBtnClick();<br />}<br />});</p><p>footPnl.add(logonBtn);<br />footPnl.add(resetBtn);<br />footPnl.add(registerBtn);<br />mainPnl.add(footPnl, BorderLayout.SOUTH);<br />this.add(topPnl, BorderLayout.NORTH);<br />this.add(mainPnl, BorderLayout.CENTER);<br />this.setLocation(200, 200);<br />this.setSize(300, 300);<br />this.setVisible(true);<br />this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />}</p><p>/**<br /> *<br /> */<br />private void logonBtnClick() {<br />new Thread() {<br />public void run() {<br />mrg.dispatch(new LogonEvent(userIdTxt.getText(), passwordTxt.getText()));<br />}<br />}.start();<br />}</p><p>/**<br /> *<br /> */<br />private void resetBtnClick() {<br />userIdTxt.setText("");<br />passwordTxt.setText("");<br />}</p><p>/**<br /> *<br /> */<br />private void regBtnClick() {<br />}</p><p>/*<br /> * (non-Javadoc)<br /> *<br /> * @see com.bzwm.testp.listener.IListener#eventCompleted(com.bzwm.testp.event.BaseEvent)<br /> */<br />public void eventCompleted(BaseEvent event) {<br />String error = event.getError();<br />if (error.equals("")) {<br />errorLbl.setText("登入成功");<br />} else {<br />errorLbl.setText(error);<br />}<br />}</p><p>public static void main(String args[]) {<br />new LoadFrame("LogonFrame");<br />}<br />}

4.LogonService.java

登入事件的邏輯處理類

實現了IService介面

package com.bzwm.testp.listener;</p><p>import com.bzwm.testp.event.BaseEvent;<br />import com.bzwm.testp.event.LogonEvent;</p><p>/**<br /> * @author bzwm<br /> *<br /> */<br />public class LogonService implements IService {</p><p>/*<br /> * (non-Javadoc)<br /> *<br /> * @see com.bzwm.testp.listener.IService#eventStarted(com.bzwm.testp.event.BaseEvent)<br /> */<br />public void eventStarted(BaseEvent event) {<br />LogonEvent logonEvent = (LogonEvent) event;<br />String id = logonEvent.getId();<br />String password = logonEvent.getPassword();<br />// 對使用者的輸入進行初步check<br />if (id == null || "".equals(id)) {<br />event.setError("使用者名稱為空白");<br />}<br />if (password == null || "".equals(password)) {<br />event.setError("密碼為空白");<br />}<br />}</p><p>/*<br /> * (non-Javadoc)<br /> *<br /> * @see com.bzwm.testp.listener.IService#service(com.bzwm.testp.event.BaseEvent)<br /> */<br />public void service(BaseEvent event) {<br />if (!event.isError()) {<br />LogonEvent logonEvent = (LogonEvent) event;<br />// 使用者id和密碼已經經過的初步check,現在去登入,檢查是否已經註冊<br />logon(logonEvent);<br />// 這裡停頓秒,算是去伺服器驗證了<br />try {<br />Thread.sleep(5000);<br />} catch (InterruptedException e) {<br />e.printStackTrace();<br />}<br />}<br />}</p><p>private void logon(LogonEvent e) {<br />// 驗證DB,使用者ID是否存在,密碼是否正確<br />// 如果不存在,則setError(),密碼不正確,setError()<br />// ...<br />}<br />}

5.EventMgr.java

管理事件

package com.bzwm.testp.common;</p><p>import com.bzwm.testp.event.BaseEvent;<br />import com.bzwm.testp.listener.IListener;<br />import com.bzwm.testp.listener.IService;<br />import java.util.ArrayList;<br />import java.util.List;</p><p>/**<br /> * @author bzwm<br /> *<br /> */<br />public class EventMgr {<br />/** 回調回主畫面的監聽集合 */<br />private List<IListener> listeners = new ArrayList<IListener>();</p><p>/** 商務邏輯的監聽集合 */<br />private List<IService> services = new ArrayList<IService>();</p><p>/**<br /> *<br /> * @param event<br /> */<br />public void dispatch(BaseEvent event) {</p><p>fireEventStarted(event);</p><p>fireEventService(event);</p><p>fireEventCompleted(event);<br />}</p><p>/**<br /> *<br /> * @param listener<br /> */<br />public void addListener(IListener listener) {<br />listeners.add(listener);<br />}</p><p>/**<br /> *<br /> * @param listener<br /> */<br />public void removeListener(IListener listener) {<br />listeners.remove(listener);<br />}</p><p>/**<br /> *<br /> * @param service<br /> */<br />public void addService(IService service) {<br />services.add(service);<br />}</p><p>/**<br /> *<br /> * @param service<br /> */<br />public void removeService(IService service) {<br />services.remove(service);<br />}</p><p>/**<br /> *<br /> * @param event<br /> */<br />private void fireEventStarted(BaseEvent event) {<br />for (IService service : services) {<br />service.eventStarted(event);<br />}<br />}</p><p>/**<br /> *<br /> * @param event<br /> */<br />private void fireEventService(BaseEvent event) {<br />for (IService service : services) {<br />service.service(event);<br />}<br />}</p><p>/**<br /> *<br /> * @param event<br /> */<br />private void fireEventCompleted(BaseEvent event) {<br />for (IListener listener : listeners) {<br />listener.eventCompleted(event);<br />}<br />}<br />}

6.BaseEvent.java

抽象類別,抽象的事件

這其中的設計還很有待商榷

package com.bzwm.testp.event;</p><p>/**<br /> * @author bzwm<br /> *<br /> */<br />public abstract class BaseEvent {</p><p>/**<br /> * 處理過程中的錯誤資訊 這裡可以選擇自訂一個Error類來完成 由於只是示範,就不寫了 另外,這種儲存error資訊的方法確實很笨<br /> */<br />private String error = "";</p><p>/**<br /> * 儲存處理返回的結果 這裡可以自訂一個Data來管理 由於是示範,也就不寫了 用一個Object返回處理結果,有很多局限性<br /> */<br />private Object result = null;</p><p>/**<br /> * @return the result<br /> */<br />public Object getResult() {<br />return result;<br />}</p><p>/**<br /> * @param result<br /> * the result to set<br /> */<br />public void setResult(Object result) {<br />this.result = result;<br />}</p><p>/**<br /> * @return the error<br /> */<br />public String getError() {<br />return error;<br />}</p><p>/**<br /> * @param error<br /> * the error to set<br /> */<br />public void setError(String error) {<br />this.error = this.error + " " + error;<br />}</p><p>public boolean isError() {<br />return !error.equals("");<br />}<br />}

7.LogonEvent.java

使用者登入事件

package com.bzwm.testp.event;</p><p>/**<br /> * @author bzwm<br /> *<br /> */<br />public class LogonEvent extends BaseEvent {</p><p>/** 使用者ID */<br />private String id = null;</p><p>/** 密碼 */<br />private String password = null;</p><p>public LogonEvent(String i, String p) {<br />setId(i);<br />setPassword(p);<br />}</p><p>/**<br /> * @return the id<br /> */<br />public String getId() {<br />return id;<br />}</p><p>/**<br /> * @param id<br /> * the id to set<br /> */<br />public void setId(String id) {<br />this.id = id;<br />}</p><p>/**<br /> * @return the password<br /> */<br />public String getPassword() {<br />return password;<br />}</p><p>/**<br /> * @param password<br /> * the password to set<br /> */<br />public void setPassword(String password) {<br />this.password = password;<br />}<br />}

 

根據上述代碼,準系統完成了。

 

也許會感覺為這一點功能寫這麼多類不值得,

但代碼會清晰一點,雖然設計上,比如類的構造上還不夠合理,

我也沒思考太多,想到這些就寫出來了。

 

不過這樣還有一個好處,比如說,你想給登入事件加輸出log的功能,

那麼比較簡單,

只要寫一個類,實現了IService即可。(因為log寫在本地檔案裡,所以不用回調回主畫面)

然後在LoadFrame.java中的構造方法改一下就OK了。

下面是輸出log用的service

 

8.LogService.java

package com.bzwm.testp.listener;</p><p>import com.bzwm.testp.event.BaseEvent;<br />import com.bzwm.testp.event.LogonEvent;</p><p>/**<br /> * @author bzwm<br /> * 關於輸出log類的設計,還可以改進,比如LogService可以是個抽象類別,下面是具體的LogonLogService,<br /> * 在父類中做一些共同的操作,比如IO操作等。<br /> * 因為很多操作都要有log,可以試著給每個畫面定義一個輸出log的類,<br /> * 專門來管理log資訊。<br /> * 這裡為簡單起見,也就不做那麼多了,並且只將資訊列印在控制台。<br /> */<br />public class LogService implements IService {</p><p>/*<br /> * (non-Javadoc)<br /> *<br /> * @see com.bzwm.testp.listener.IService#eventStarted(com.bzwm.testp.event.BaseEvent)<br /> */<br />public void eventStarted(BaseEvent event) {<br />// TODO Auto-generated method stub<br />if (event instanceof LogonEvent) {<br />LogonEvent e = (LogonEvent) event;<br />System.out.println(e.getId() + " 準備登入了");<br />}<br />}</p><p>/*<br /> * (non-Javadoc)<br /> *<br /> * @see com.bzwm.testp.listener.IService#service(com.bzwm.testp.event.BaseEvent)<br /> */<br />public void service(BaseEvent event) {<br />// TODO Auto-generated method stub<br />if (event instanceof LogonEvent) {<br />LogonEvent e = (LogonEvent) event;<br />String error = e.getError();<br />if (error.equals("")) {<br />System.out.println(e.getId() + " 登入了");<br />} else {<br />System.out.println(e.getId() + " 登入失敗了 " + error);<br />}<br />}<br />}<br />}

接著,改 LoadFrame.java類。

唯寫出改的部分,它的構造方法:

public LoadFrame(String title) {<br />super(title);<br />initComponents();<br />layoutComponents();<br />mrg = new EventMgr();<br />// 追加監聽器<br />mrg.addListener(this);<br />mrg.addService(new LogonService());<br />mrg.addService(new LogService());<br />}

這樣,把代碼拷貝下來,

重新運行下,就出現log了。

 

這隻是登入的功能,

如果還要完成註冊的功能,

則還是一樣的步驟,

寫一個Dialog類,繼承JDialog,實現IListener介面,

定義一個RegEvent.java繼承BaseEvent.java,

寫一個RegService類,實現IService介面,

總之把相應包下面,加入自己的實現,

然後將監聽還是註冊到EventMgr裡就可以實現了。

 

好了。歡迎交流,謝謝!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.