一般來說,可以把系統粗略的分爲三個層次,視圖層,簡稱爲 View,它負責數據的輸出和輸入;業務層,簡稱爲 Model,它代表程序的實際業務;控制層,簡稱爲 Controller,處理界面的相應並調用業務層進行處理,有時把 View和 Controller兩層合稱爲 UI層。
在程序發展的歷史上, MVC模式進過了多次演化, MVC1和 MVC2是兩種比較典型的模式,它們的區別主要在於 View和 Model的聯繫方式上。
( 1 ) MVC1 模式
這種模式主要用於桌面程序 ,使用觀察者模式實現 ,具體來說就是讓 View充當觀察者來觀察 Model的變化 ,而用戶交互控制的地方用匿名類的方式統一放在 controller中 .
View接受用戶輸入 ,並將交互數據傳遞到 Controller.
Controller統一進行處理命令 ,交由 Model處理具體的業務 .
進過處理 Model更新後 ,通知 View進行更新 .
這種模式在舊的桌面應用程序使用較多,但是它的
Model必須繼承
Observable類,
View必須實現
Observer接口,人爲加大了繼承體系的複雜度;而且
Model通知
View的方式使
View必須瞭解
Model的結構,無謂的加大了兩個類的耦合程度。這些缺點使這種模式逐漸淡出了程序舞臺。
代碼如下:
Control類:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* 控制類
*
* @author sitinspring([email protected])
*
* @date 2007-11-5
*/
public class Mvc1Ctrl {
private Mvc1View view;
private Mvc1Model model;
public Mvc1Ctrl() {
view = new Mvc1View();
model = new Mvc1Model();
model.addObserver(view);
handleEvents();
}
// 處理事件響應
private void handleEvents() {
addCloseLintener();
addButtonListener();
addButtonListener2();
}
// 窗體關閉事件相應
private void addCloseLintener() {
view.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println( " Exit MVC1 " );
System.exit( 0 );
}
} );
}
private void addButtonListener() {
view.getButton().addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.showText();
}
} );
}
private void addButtonListener2() {
view.getButton2().addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.showText2();
}
} );
}
}
視圖類(View) :
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
/**
* 視圖類(View)
*
* @author sitinspring([email protected])
*
* @date 2007-11-5
*/
public class Mvc1View extends JFrame implements Observer {
private static final long serialVersionUID = 621145935910133202L ;
private JButton button;
private JLabel label;
private JButton button2;
private JLabel label2;
public Mvc1View() {
locateView( 300 , 200 );
this .setTitle( " MVC1 Program " );
setupComponents();
this .setVisible( true );
}
// 當模塊更新時,此函數會被調用
public void update(Observable o, Object arg) {
Mvc1Model model = (Mvc1Model) o;
if (model.getUpdateState().equals(Mvc1UpdateState.UpdateLabel)) {
label.setText(model.getResponseText());
} else if (model.getUpdateState().equals(Mvc1UpdateState.UpdateLabel2)) {
label2.setText(model.getResponseText());
}
}
// 定位程序在屏幕正中並設置程序大小
private void locateView( int width, int height) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this .setSize(width, height);
this .setLocation(screenSize.width / 2 - width / 2 , screenSize.height
/ 2 - height / 2 );
}
// 初始化內部組件
private void setupComponents() {
button = new JButton( " 點擊響應事件1 " );
label = new JLabel( " 等待事件響應1 " );
button2 = new JButton( " 點擊響應事件2 " );
label2 = new JLabel( " 等待事件響應2 " );
setLayout( new GridLayout( 2 , 2 ));
add(button);
add(label);
add(button2);
add(label2);
}
public JButton getButton() {
return button;
}
public JButton getButton2() {
return button2;
}
}
模塊類 :
import java.util.Observable;
/**
* 模塊類
* @author sitinspring([email protected])
*
* @date 2007-11-5
*/
public class Mvc1Model extends Observable {
private String responseText;
private String updateState;
// 用於通知View更新,此函數被調用後View的update函數會被調用
private void notifyView() {
setChanged();
notifyObservers();
}
public void showText() {
updateState = Mvc1UpdateState.UpdateLabel;
responseText = " 事件1響應完畢 " ;
notifyView();
}
public void showText2() {
updateState = Mvc1UpdateState.UpdateLabel2;
responseText = " 事件2響應完畢 " ;
notifyView();
}
public String getResponseText() {
return responseText;
}
public String getUpdateState() {
return updateState;
}
}
更新狀態輔助類:
public class Mvc1UpdateState {
public static final String UpdateLabel = " updateLabel " ;
public static final String UpdateLabel2 = " updateLabel2 " ;
}
MVC1示例代碼下載:
http://www.blogjava.net/Files/sitinspring/MVC1.rar
(
2)
MVC2模式
這種模式首見於網絡程序,起初因爲 Model無法通知到 Web程序的界面而發明,這種模式採用 Controller做中介者,一方面取得 View的輸入,然後交由 Model層處理,之後再把返回的數據傳遞到 View。
View接受用戶輸入 ,並傳遞到 Controller.
Controller統一進行處理命令 ,交由 Model處理具體的業務 .
進過處理 Model更新後 ,Controller會選一個 View並把 Model內容傳遞 (request,session)給它 (forward).
然後 View進行顯示 .
這種模式相對
MVC
優勢很明顯,首先
Model
和
View
無需繼承甚麼東西,其次
Model
和
View
無需瞭解對方的存在,只需準備相應的接口而已;缺點是
Controller
層變得相對複雜了。
代碼如下:
控制類:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* 控制類
*
* @author sitinspring([email protected])
*
* @date 2007-11-5
*/
public class Mvc2Ctrl {
private Mvc2View view;
private Mvc2Model model;
public Mvc2Ctrl() {
view = new Mvc2View();
model = new Mvc2Model();
handleEvents();
}
// 處理事件響應
private void handleEvents() {
addCloseLintener();
addButtonListener();
addButtonListener2();
}
// 窗體關閉事件相應
private void addCloseLintener() {
view.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println( " Exit MVC2 " );
System.exit( 0 );
}
} );
}
private void addButtonListener() {
view.getButton().addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
view.getLabel().setText(model.getText());
}
} );
}
private void addButtonListener2() {
view.getButton2().addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
view.getLabel2().setText(model.getText2());
}
} );
}
}
視圖類:
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
/**
* 視圖類(View)
*
* @author sitinspring([email protected])
*
* @date 2007-11-5
*/
public class Mvc2View extends JFrame {
private static final long serialVersionUID = 621145935910133202L ;
private JButton button;
private JLabel label;
private JButton button2;
private JLabel label2;
public Mvc2View() {
locateView( 300 , 200 );
this .setTitle( " MVC2 Program " );
setupComponents();
this .setVisible( true );
}
// 定位程序在屏幕正中並設置程序大小
private void locateView( int width, int height) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this .setSize(width, height);
this .setLocation(screenSize.width / 2 - width / 2 , screenSize.height
/ 2 - height / 2 );
}
// 初始化內部組件
private void setupComponents() {
button = new JButton( " 點擊響應事件1 " );
label = new JLabel( " 等待事件響應1 " );
button2 = new JButton( " 點擊響應事件2 " );
label2 = new JLabel( " 等待事件響應2 " );
setLayout( new GridLayout( 2 , 2 ));
add(button);
add(label);
add(button2);
add(label2);
}
public JButton getButton() {
return button;
}
public JButton getButton2() {
return button2;
}
public JLabel getLabel() {
return label;
}
public JLabel getLabel2() {
return label2;
}
}
模塊類:
/**
* 模塊類
* @author sitinspring([email protected])
*
* @date 2007-11-5
*/
public class Mvc2Model {
public String getText() {
return " 事件1響應完畢 " ;
}
public String getText2() {
return " 事件2響應完畢 " ;
}
}
MVC2示例代碼下載:
http://www.blogjava.net/Files/sitinspring/MVC2.rar