<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    HelloWorld 善戰者,求之于勢,不責于人;故能擇人而任勢。

    知止而后有定,定而后能靜,靜而后能安,安而后能慮,慮而后能得。物有本末,事有終始。知所先后,則近道矣。

      BlogJava :: 首頁 ::  :: 聯系 ::  :: 管理 ::
      167 隨筆 :: 1 文章 :: 40 評論 :: 0 Trackbacks

    實戰MVC模式

    MVC

    “模型-視圖-控制器(Model-View-Controller,MVC)結構是為那些需要為同樣的數據提供多個視圖的應用程序而設計的,它很好的實現了數據層與表示層的分離。例如下圖中的例子:

     

    MVC

    我們看到,圖中的幾組數據以不同的形式(View)表現出來,一個是表格樣式,一個是圖形樣式。

    MVC通信方式

    MVC把這種應用程序分為三種對象類型:

     

    • 模型:維護數據并提供數據訪問方法。
    • 視圖:給制模型的部分數據或所有數據的可視圖。
    • 控制器:處理事件.

    以下是典型的MVC通信方式,

    [{MVC_1.gif][MVC的通信方式]]

    1. 事件由控制器來處理,控制器接收用戶事件,并根據事件的類型來改變模型。
    2. 視圖事先會在模型中登記,當模型數據發生改變時,馬上通知已向此模型登記的每個視圖。
    3. 視圖從模取得最新的數據并刷新自己.

    要實現MVC,最重要的一個環節是使用Design Pattern中的Observer模式。Observer模式允許某個對象在所觀察的對象發生修改時通知多個觀察者(Observer).

    下面我們就以實例來講解如何用Obserer模式實現MVC的程序結構。在我的例子中,我要實現一個學生年齡顯示的例子。分別用清單和圖形的方式顯示每個學生的年齡。當年齡改變時,自動更新顯示。

    Observer接口

    為了實現觀察的對象發生修改時通知多個觀察者,通常要在被觀察者與觀察者之間有一個小的接口,如下:
    /* file: Observer.java */
    public interface Observer {
    public void dataUpdate(Model model);
    }
    

    這個接口中有一個 dataUpdate(Model model) 方法,只要實現了這個接口對象,就成了一個觀察者。

    模型Model

    再來建立一個數據模型。在我的例子中,先建立了一個數據對象:

     

    /* file: Data.java */
    public class Data {
    public int value; // 學生年齡值
    
    public String name; // 學生名
    }
    

    現在來建立一個 Model :

    /* file: Model.java */
    import java.util.*;
    public class Model {
    ArrayList data = new ArrayList();
    ArrayList observer = new ArrayList();
    public Model() {
    super();
    }
    public Model(int[] value, String[] name) {
    for (int i = 0; i < value.length; i++) {
    addData(value[i], name[i]);
    }
    }
    public Model(Data[] data) {
    for (int i = 0; i < data.length; i++) {
    addData(data[i]);
    }
    }
    public void addData(int value, String name) {
    Data data = new Data();
    data.value = value;
    data.name = name;
    this.data.add(data);
    }
    public void addData(Data data) {
    this.data.add(data);
    }
    public Data getData(int idx) {
    return (Data) (data.get(idx));
    }
    public int size() {
    return data.size();
    }
    // 用來向模型中登記觀察者.
        public void registerObserver(Observer o) {
    observer.add(o);
    }
    public void removeObserver(Observer o) {
    observer.remove(o);
    }
    // 當數據改變時,由Controller調用此方法,通知各個Observer,刷新視圖.
        public void changeModel(Model model) {
    data.clear();
    for (int i = 0; i < model.size(); i++) {
    this.addData(model.getData(i));
    }
    dataUpdate();
    }
    private void dataUpdate() {
    for (Iterator i = observer.iterator(); i.hasNext();) {
    Observer o = (Observer) (i.next());
    o.dataUpdate(this);
    }
    }
    }
    

    這個模型提供各種數據訪問的方法。并提供一個 changeModel(Model model) 方法供 Controller 訪問。還提供一個 registerObserver(Observer o) 方法,用來向 Model 中登記觀察者 Observer

    視圖View

    我們要實現一個清單顯示樣式的視圖 View1 和一個圖形方式顯示的視圖 View2 ,并讓它們實現 Observer 接口,以便當 Model 數據改變時,自動刷新自己.
    /* file: View1.java */
    import javax.swing.*;
    import java.awt.*;
    import javax.swing.border.*;
    public class View1 extends JPanel implements Observer {
    Model model;
    public View1() {
    }
    public View1(Model model) {
    try {
    this.model = model;
    jbInit();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    private void jbInit() throws Exception {
    this.setBackground(Color.white);
    this.setBorder(new TitledBorder(BorderFactory.createLineBorder(
    Color.black, 1), "View1"));
    }
    public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (model == null)
    return;
    int x = 20, y = 50;
    int h = g.getFontMetrics().getHeight();
    for (int i = 0; i < model.size(); i++) {
    Data data = model.getData(i);
    g.drawString(data.name, x, y);
    y += h;
    g.drawString(String.valueOf(data.value), x, y);
    y += h;
    }
    }
    // 當模型數據發生改變時,會自動調用此方法來刷新圖形
        public void dataUpdate(Model model) {
    /** @todo: Implement this Observer method */
    this.model = model;
    repaint();
    }
    }
    

    View2.java

    /* file: View2.java */
    import javax.swing.*;
    import java.awt.*;
    import javax.swing.border.*;
    public class View2 extends JPanel implements Observer {
    Model model;
    public View2() {
    }
    public View2(Model model) {
    try {
    this.model = model;
    jbInit();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    private void jbInit() throws Exception {
    this.setBackground(Color.white);
    this.setBorder(new TitledBorder(BorderFactory.createLineBorder(
    Color.black, 1), "View1"));
    }
    public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (model == null)
    return;
    int x = 20, y = 50;
    int h = g.getFontMetrics().getHeight();
    int width = this.getWidth();
    int height = this.getHeight();
    int sy = height / model.size();
    int sx = width / 2;
    for (int i = 0; i < model.size(); i++) {
    Data data = model.getData(i);
    int value = data.value;
    int dx = 3;
    int r = 3;
    Color c = new Color((int) (255 * Math.random()), (int) (255 * Math
    .random()), (int) (255 * Math.random()));
    int cx = sx;
    int cy = y + i * sy;
    for (int j = 0; j < value; j++) {
    g.setColor(c);
    g.drawOval(cx, cy, r, r);
    r += dx;
    }
    g.drawString(data.name, 25, cy);
    }
    }
    // 當模型數據發生改變時,會自動調用此方法來刷新圖形
        public void dataUpdate(Model model) {
    /** @todo: Implement this Observer method */
    this.model = model;
    repaint();
    }
    }
    

    控制器Controller

    好了,MVC中的 Model , Observer 都建立好了,我們最后來做一個 Controller :

     

    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    public class Controller extends JFrame {
    Model model = new Model();
    View1 view1 = new View1(model);
    View2 view2 = new View2(model);
    JScrollPane jScrollPane1 = new JScrollPane();
    JButton jButton1 = new JButton();
    JTextField jTextField1 = new JTextField();
    JTextField jTextField2 = new JTextField();
    JLabel jLabel1 = new JLabel();
    JLabel jLabel2 = new JLabel();
    JLabel jLabel3 = new JLabel();
    public Controller() {
    try {
    jbInit();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    private void jbInit() throws Exception {
    Data[] data = new Data[2];
    data[0] = new Data();
    data[1] = new Data();
    data[0].name = "Ted";
    data[0].value = 20;
    data[1].name = "Joy";
    data[1].value = 14;
    model.addData(data[0]);
    model.addData(data[1]);
    // 注意下面兩行:向模型中登記它的觀察者View1和View2.
            model.registerObserver(view1);
    model.registerObserver(view2);
    this.getContentPane().setLayout(null);
    jScrollPane1.setBounds(new Rectangle(0, 0, 3, 3));
    jButton1.setBounds(new Rectangle(309, 259, 101, 27));
    jButton1.setText("Update");
    jButton1.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(ActionEvent e) {
    jButton1_actionPerformed(e);
    }
    });
    jTextField1.setText("20");
    jTextField1.setBounds(new Rectangle(80, 254, 52, 30));
    jTextField2.setText("14");
    jTextField2.setBounds(new Rectangle(178, 255, 50, 31));
    jLabel1.setText("Age:");
    jLabel1.setBounds(new Rectangle(41, 226, 47, 23));
    jLabel2.setText("Ted");
    jLabel2.setBounds(new Rectangle(42, 252, 35, 33));
    jLabel3.setText("Joy");
    jLabel3.setBounds(new Rectangle(144, 255, 31, 31));
    view1.setBounds(new Rectangle(7, 5, 225, 208));
    view2.setBounds(new Rectangle(234, 4, 219, 209));
    this.getContentPane().add(jScrollPane1, null);
    this.getContentPane().add(jTextField2, null);
    this.getContentPane().add(jTextField1, null);
    this.getContentPane().add(jLabel2, null);
    this.getContentPane().add(jLabel3, null);
    this.getContentPane().add(jLabel1, null);
    this.getContentPane().add(jButton1, null);
    this.getContentPane().add(view1, null);
    this.getContentPane().add(view2, null);
    }
    // 按下Update按鈕,通知Model數據發生改變.
        void jButton1_actionPerformed(ActionEvent e) {
    Data[] data = new Data[2];
    data[0] = new Data();
    data[1] = new Data();
    data[0].name = jLabel1.getText();
    data[0].value = Integer.parseInt(jTextField1.getText());
    data[1].name = jLabel2.getText();
    data[1].value = Integer.parseInt(jTextField2.getText());
    Model m = new Model(data);
    this.model.changeModel(m);
    }
    public static void main(String[] args) {
    Controller c = new Controller();
    c.setSize(475, 310);
    c.setVisible(true);
    }
    }
    

    運行程序

    各位可以將這些代碼各自存為相應的源文件,執行以下命令編譯

    javac Controller.java

    運行

    java Controller.class

    就可以看到程序執行的效果,

    執行結果示圖

    你可以試著改變兩個學生的年齡,按一下 Update 按鈕,相應的視圖就更新了。怎么樣,體驗到了MVC結構給程序帶來的方便性了吧?;)

    大家如果運行程序有任何問題,或需編譯好的程序,可與我聯絡。

    關于作者

    陳先波(turbochen)是賽微科技公司(www.qissoft.com)的Java開發員,曾為多個技術網站撰稿。有超過三年的Java開發經驗,主要致力于Java技術在質量管理信息系統中的應用,請通過turbochen@163.com與作者聯系。

    </script>

    posted on 2008-02-15 15:26 helloworld2008 閱讀(181) 評論(0)  編輯  收藏 所屬分類: java
    主站蜘蛛池模板: 久久久久久AV无码免费网站下载| 亚洲国产精品一区二区三区在线观看| 成在人线av无码免费高潮喷水| 免费jjzz在在线播放国产| 一个人看的www免费在线视频| 久久久久亚洲精品成人网小说| 我的小后妈韩剧在线看免费高清版| 337p日本欧洲亚洲大胆人人 | 99久久精品日本一区二区免费| 亚洲精品永久在线观看| 亚洲精品在线免费观看视频| 亚洲av无码一区二区乱子伦as | 中文字幕人成无码免费视频 | 少妇性饥渴无码A区免费| 免费观看的a级毛片的网站| 亚洲综合日韩中文字幕v在线 | 2015日韩永久免费视频播放| 亚洲最大成人网色香蕉| 91老湿机福利免费体验| 亚洲一区AV无码少妇电影☆| xxxx日本在线播放免费不卡| 18禁成人网站免费观看| 亚洲深深色噜噜狠狠爱网站| 日日摸日日碰夜夜爽亚洲| 免费精品国产自产拍在线观看图片 | 欧美好看的免费电影在线观看| 亚洲va在线va天堂成人| 国产精品小视频免费无限app | 国产免费私拍一区二区三区| 一级女人18片毛片免费视频| 亚洲黄色在线观看视频| 无码国产亚洲日韩国精品视频一区二区三区| 亚洲视频在线不卡| 一级特黄a大片免费| 免费h黄肉动漫在线观看| 亚洲精品色在线网站| 亚洲AV无码国产精品麻豆天美| 欧洲美熟女乱又伦免费视频| 久久精品免费视频观看| 久久青青草原亚洲av无码app | 蜜臀AV免费一区二区三区|