實(shí)戰(zhàn)MVC模式

          ?內(nèi)容:
          1.MVC
          2.Observer接口
          3.模型Model
          4.視圖View
          5.控制器Controller
          6.運(yùn)行程序??


          --------------------------------------------------------------------------------


          MVC

          “模型-視圖-控制器(Model-View-Controller,MVC)結(jié)構(gòu)是為那些需要為同樣的數(shù)據(jù)提供多個(gè)視圖的應(yīng)用程序而設(shè)計(jì)的,它很好的實(shí)現(xiàn)了數(shù)據(jù)層與表示層的分離。例如下圖中的例子:

          我們看到,圖中的幾組數(shù)據(jù)以不同的形式(View)表現(xiàn)出來,一個(gè)是表格樣式,一個(gè)是圖形樣式。

          MVC把這種應(yīng)用程序分為三種對象類型:
          模型:維護(hù)數(shù)據(jù)并提供數(shù)據(jù)訪問方法。
          視圖:給制模型的部分?jǐn)?shù)據(jù)或所有數(shù)據(jù)的可視圖。
          控制器:處理事件.
          以下是典型的MVC通信方式,


          事件由控制器來處理,控制器接收用戶事件,并根據(jù)事件的類型來改變模型。
          視圖事先會(huì)在模型中登記,當(dāng)模型數(shù)據(jù)發(fā)生改變時(shí),馬上通知已向此模型登記的每個(gè)視圖。
          視圖從模取得最新的數(shù)據(jù)并刷新自己.
          要實(shí)現(xiàn)MVC,最重要的一個(gè)環(huán)節(jié)是使用Design??Pattern中的Observer模式。Observer模式允許某個(gè)對象在所觀察的對象發(fā)生修改時(shí)通知多個(gè)觀察者(Observer).

          下面我們就以實(shí)例來講解如何用Obserer模式實(shí)現(xiàn)MVC的程序結(jié)構(gòu)。在我的例子中,我要實(shí)現(xiàn)一個(gè)學(xué)生年齡顯示的例子。分別用清單和圖形的方式顯示每個(gè)學(xué)生的年齡。當(dāng)年齡改變時(shí),自動(dòng)更新顯示。

          Observer接口

          為了實(shí)現(xiàn)觀察的對象發(fā)生修改時(shí)通知多個(gè)觀察者,通常要在被觀察者與觀察者之間有一個(gè)小的接口,如下:
          /*??file:??Observer.java??*/
          public??interface??Observer
          {
          ????????public??void??dataUpdate(Model??model);
          }
          這個(gè)接口中有一個(gè)dataUpdate(Model??model)方法,只要實(shí)現(xiàn)了這個(gè)接口對象,就成了一個(gè)觀察者。

          模型Model

          再來建立一個(gè)數(shù)據(jù)模型。在我的例子中,先建立了一個(gè)數(shù)據(jù)對象:
          /*??file:??Data.java??*/
          public??class??Data
          {
          ????????public??int??value;  //??學(xué)生年齡值
          ????????public??String??name; //??學(xué)生名
          }
          現(xiàn)在來建立一個(gè)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,name);
          ????????????????}
          ????????}
          ????????public??Model(Data[]??data)
          ????????{
          ????????????????for??(??int??i??=??0;??i<??data.length;??i++??
          ????????????????{
          ????????????????????????addData(data);
          ????????????????}
          ????????}
          ????????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);
          ????????}
          ????????//??當(dāng)數(shù)據(jù)改變時(shí),由Controller調(diào)用此方法,通知各個(gè)Observer,刷新視圖.
          ????????public??void??changeModel(Model??model)
          ????????{
          ????????????????data.clear();
          ????????????????for??(int??i=0;??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);
          ????????????????}
          ????????}
          }
          這個(gè)模型提供各種數(shù)據(jù)訪問的方法。并提供一個(gè)changeModel(Model??model)方法供Controller訪問。還提供一個(gè)registerObserver(Observer??o)方法,用來向Model中登記觀察者Observer。

          視圖View

          我們要實(shí)現(xiàn)一個(gè)清單顯示樣式的視圖View1和一個(gè)圖形方式顯示的視圖View2,并讓它們實(shí)現(xiàn)Observer接口,以便當(dāng)Model數(shù)據(jù)改變時(shí),自動(dòng)刷新自己.
          /*??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;
          ????????????????}
          ????????}
          ????????//??當(dāng)模型數(shù)據(jù)發(fā)生改變時(shí),會(huì)自動(dòng)調(diào)用此方法來刷新圖形
          ????????public??void??dataUpdate(Model??model)
          ????????{
          ????????????????/**@todo:??Implement??this??Observer??method*/
          ????????????????this.model??=??model;
          ????????????????repaint();
          ????????}
          }
          /*??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
          ????????????????????????{
          ????????????????????????????????g.setColor(c);
          ????????????????????????????????g.drawOval(cx,cy,r,r);
          ????????????????????????????????r+=dx;
          ????????????????????????}
          ????????????????????????g.drawString(data.name,25,cy);
          ????????????????}
          ????????}
          ????????//??當(dāng)模型數(shù)據(jù)發(fā)生改變時(shí),會(huì)自動(dòng)調(diào)用此方法來刷新圖形
          ????????public??void??dataUpdate(Model??model)
          ????????{
          ????????????????/**@todo:??Implement??this??Observer??method*/
          ????????????????this.model??=??model;
          ????????????????repaint();
          ????????}
          }

          控制器Controller

          好了,MVC中的Model,Observer都建立好了,我們最后來做一個(gè)Controller:
          import??java.awt.*;
          import??javax.swing.*;
          import??javax.swing.border.*;
          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,??20);
          ????????????????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數(shù)據(jù)發(fā)生改變.
          ????????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);
          ????????}
          }

          運(yùn)行程序

          各位可以將這些代碼各自存為相應(yīng)的源文件,執(zhí)行以下命令編譯
          javac??Controller.java
          運(yùn)行
          java??Controller.class
          就可以看到程序執(zhí)行的效果,



          你可以試著改變兩個(gè)學(xué)生的年齡,按一下Update按鈕,相應(yīng)的視圖就更新了。怎么樣,體驗(yàn)到了MVC結(jié)構(gòu)給程序帶來的方便性了吧?;

          posted on 2007-03-09 01:40 金家寶 閱讀(246) 評論(0)  編輯  收藏 所屬分類: J2EE技術(shù)實(shí)例


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 秦皇岛市| 苏尼特左旗| 庐江县| 平湖市| 老河口市| 郎溪县| 历史| 米易县| 屏边| 谷城县| 石泉县| 同江市| 确山县| 潞西市| 拉萨市| 凉城县| 揭东县| 宣威市| 佛山市| 田林县| 双牌县| 潜江市| 临颍县| 青海省| 蓬溪县| 钟祥市| 任丘市| 龙川县| 通辽市| 宣威市| 新巴尔虎右旗| 航空| 宜川县| 武川县| 德钦县| 赤城县| 兴山县| 彭州市| 新竹市| 阿拉善右旗| 平昌县|