foolish
2006-11-24 13:14:57 UTC
※ 引述《neigence (心夜)》之銘言:
: 假如我有一個程式
: public class myFrame extends JFrame{
: public AAA(){
: Container con=getContentPane();
: con.add(myPanelA);
: con.add(myPanelB);
: con.add(myPanelC);
: .....
: }
: }
: 每一個panel都也許具有許多的gui元件 像JButton JTextfield
: 每一個panel都在不同的class
: 比方說 我按下myPanelB上的某個button 會影響讓myPanelA畫出
: 什麼東西 或發生某些行為 或更動變數狀態
: 那..理論上? 這幾個myPanel下所有gui元件的ActionListener
: 都要寫在myFrame這個程式下面嚕?..這樣子光這個檔下面的
: actionPerformed 真的會太多了
++myFrame+++++++++++++++++: 假如我有一個程式
: public class myFrame extends JFrame{
: public AAA(){
: Container con=getContentPane();
: con.add(myPanelA);
: con.add(myPanelB);
: con.add(myPanelC);
: .....
: }
: }
: 每一個panel都也許具有許多的gui元件 像JButton JTextfield
: 每一個panel都在不同的class
: 比方說 我按下myPanelB上的某個button 會影響讓myPanelA畫出
: 什麼東西 或發生某些行為 或更動變數狀態
: 那..理論上? 這幾個myPanel下所有gui元件的ActionListener
: 都要寫在myFrame這個程式下面嚕?..這樣子光這個檔下面的
: actionPerformed 真的會太多了
| |
| A panel Button |
| |
+-------------------------
| |
| B panel Text |
| |
+-------------------------
| |
| C panel Label |
| |
+-------------------------
你可能在B text填了什麼,
按了A的Button之後,想透過C的Label顯示點什麼訊息
所以直覺想幫A加了一個ActionListener
{
取得ORZ = B.text
經過謎樣的邏輯運算後 XD = cal(ORZ)
顯示結果在C之中 C.label = XD
}
這只是一種初步的想法,當你的Component很多的時候
就會難以控制。因為任何的Component都可能產生關係
要站在某一方(ex. A's Listener)的觀點去操控其他所有的元件
會增加程式設計師的負擔。
for example:
ActionListener
{
t1 = A.xd;
B.label = func1(t1)
C.label = func2(t1)
D.label = func3(t1)
t2 = sum({B, C, D}.label)
............
........
....
.
}
這樣一來計算過還可能有些用處的資料,都散落在各個元件之中。
還要一一再收回? 可能會瘋掉。
===========================================================
Tip 1 :: GUI的資料要獨立且唯一
為了解決資料散落於各元件的問題,我們應該建立新的Class來表現
我們所用來展示、算計、暫存用的資料,有續存的需求更可以實作
Serializable。
所以,先讓資料獨立出來。
public class CheckableData {
private String foo;
public void setData(String f){foo=f;}
}
Tip 2 :: 不要讓運算邏輯散落於Listener之中
讓Data的歸Data的,使用者介面的歸使用者介面的
假設我們要讓資料可序列化,你不可以把序列化的主要部分寫在
Action之中。應該擺在CheckableData這裡才對 (ex. save method)
==========================================================
以提供base64 encode為例:
import sun.misc.BASE64Encoder;
public class CheckableData {
private String foo;
public void setData(String f) {
foo = f;
}
public String getEncodeAsBase64() {
return new BASE64Encoder().encode(foo.getBytes());
}
}
(bad style)
encode_button.addActionListener(){
.........................
xd.label = new BASE64Encoder().encode(foo.getBytes());
}
這樣做的好處是,邏輯運算的部分幾乎都可以回歸資料本身。
達到純粹send message來溝通。
========================================================
即使經過了Tip 1、Tip 2資料獨立了,邏輯計算都歸位了。
你可能還是望著內容不少的Listener而懊惱。
這是怎麼一回事呢? 我們還需要改變些什麼!?
回過頭來看一下Listener
{
取得ORZ = B.text
經過謎樣的邏輯運算後 XD = cal(ORZ)
顯示結果在C之中 C.label = XD
}
這是在按了某個東西,觸發了事件。
最後導致了C.label更新
許多入門的書可能都是這樣寫了
按了foo,計算一下,直接更新了bar
這是個很直覺的構想,也不用覺得寫書的人有什麼不錯
因為他的重點在介面GUI,而我們今天的重點在
怎麼讓自己程式寫起來負擔小一點,
不會把code都擠在一起。
所以,為了我們的睡眠品質與減輕壓力應該想一想
是否有較好的方式,懶人思維: 是不是能讓C.label
自己更新自己
(general case: 讓(..)自己更新自己)
如果成真了這樣一來,就能讓Listener中更新
其他元件的code消失,而Listener只要通知Data object
去計算資料即可
=====================================================
Tip 3 :: 讓需要取得資料者成為觀察者
(提供資料的為被觀察者)
j2se提供了這樣的機制
Interface Observer
void update(Observable o, Object arg)
Class Observable
addObserver(Observer o)
notifyObservers()
setChanged()
這要怎麼用呢!?
Observer --> 需要取用資料者
Observable --> 持有/產生資料者
以我們的例子,CheckableData是產生資料者:
import java.util.Observable;
import sun.misc.BASE64Encoder;
public class CheckableData extends Observable {
private String foo;
public void setData(String f) {
foo = f;
this.setChanged(); // 標示,我"變"了
this.notifyObservers(); // 昭告天下,我真的"變了"
}
public String getEncodeAsBase64() {
return new BASE64Encoder().encode(foo.getBytes());
}
}
======================================================
import java.util.Observable;
import java.util.Observer;
import javax.swing.JLabel;
public class ObLabel extends JLabel implements Observer {
private String label;
public ObLabel(Observable o , String s) {
o.addObserver(this);
label = s;
}
public void setLabel(String s) {
this.label = s;
this.setText(s);
}
public void update(Observable o, Object arg) {
if (o instanceof CheckableData) {
CheckableData cd = (CheckableData) o; // 取得資料
setLabel(cd.getEncodeAsBase64()); // 自己更新自己
}
}
}
如此一來,則所有元件可以透過觀察CheckableData來自動更新。
Listener所負擔的code也就少了,複雜的元件關係也獲得了解脫。
--
偷偷講,其實這是簡單的講怎麼做mvc @"@
mvc 是策略模式+觀察著模式與一些互動的規範而成。
此篇稍略了策略模式,但大致上還算可用
--
[1;32m※ Origin: [33mSayYA 資訊站 [37m<bbs.sayya.org> [m
[1;31m◆ From: [36mpc210-59-94-161.nutn.edu.tw[m