MVC模式介紹
模型-視圖-控制器(Model-View-Controller,MVC)模式就是為那些需要為同樣的數(shù)據(jù)提供多個視圖的應用程序而設計的。它很好地實現(xiàn)了數(shù)據(jù)層與表示層的分離,特別適用于開發(fā)與用戶圖形界面有關的應用程序,其示意圖見圖1。模式中基本結(jié)構(gòu)定義為:
控制器 用來處理用戶命令以及程序事件的;
模型 維護數(shù)據(jù)并提供數(shù)據(jù)訪問方法;
視圖 數(shù)據(jù)的顯示。
MVC模式基本實現(xiàn)過程為:
1. 控制器(如Java中的main程序入口)要新建模型;
2. 控制器要新建一個或多個視圖對象,并將它們與模型相關聯(lián);
3. 控制器改變模型的狀態(tài);
4. 當模型的狀態(tài)改變時,模型將會自動刷新與之相關的視圖。
圖1 MVC模式基本結(jié)構(gòu)
本文要實現(xiàn)的Java應用程序是當用戶在圖形化用戶界面輸入一個球體的半徑時,程序?qū)@示該球體的體積與表面積。我們首先利用基本MVC模式實現(xiàn)以上程序,然后利用不同數(shù)量的模型、視圖、控制器結(jié)構(gòu)來擴展該程序。
基本MVC模式
該程序主要由三個類構(gòu)成,分別為Sphere類、TextView類及SphereWindow類。其中Sphere類扮演Model的角色,TextView類為View角色,SphereWindow類為Controller角色。
Java通過專門的類Observable及Observer接口來實現(xiàn)MVC編程模式。其UML類圖及MVC模式的實現(xiàn)方式見圖2。
圖2 MVC模式的UML類圖
從圖2中可以看出,Model類必須繼承Observable類,View類必須實現(xiàn)接口Observer。正是由于實現(xiàn)了上述結(jié)構(gòu),當模型發(fā)生改變時(當控制器改變模型的狀態(tài)),模型就會自動刷新與之相關的視圖。其UML序列圖可以表示為圖3。
Model類Sphere,必須擴展Observable類,因為在Observable類中,方法addObserver()將視圖與模型相關聯(lián),當模型狀態(tài)改變時,通過方法notifyObservers()通知視圖。其中實現(xiàn)MVC模式的關鍵代碼為:
import java.util.Observable; class Sphere extends Observable { .... public void setRadius(double r) { myRadius = r; setChanged(); // Indicates that the model has changed notifyObservers(); } .... } |
圖3 MVC模式的UML序列圖
View類的角色TextView類必須實現(xiàn)接口Observer,這意味著類TextView必須是implements Observe,另外還需實現(xiàn)其中的方法update()。有了這個方法,當模型Sphere類的狀態(tài)發(fā)生改變時,與模型相關聯(lián)的視圖中的update()方法就會自動被調(diào)用,從而實現(xiàn)視圖的自動刷新。View類的關鍵代碼如下:
import java.util.Observer; import java.util.Observable; public class TextView extends JPanel implements Observer { ...... public void update(Observable o, Object arg) { Sphere balloon = (Sphere)o; radiusIn.setText(“ ”+f3.format(balloon.getRadius())); volumeOut.setText(“ ”+f3.format(balloon.volume())); surfAreaOut.setText(“ ” + f3.format(balloon.surfaceArea())); } ...... } |
SphereWindow類作為Controller,它主要新建Model與View,將view與Model相關聯(lián),并處理事件,其中的關鍵代碼為:
public SphereWindow() { super(“Spheres: volume and surface area”); model = new Sphere(0, 0, 100); TextView view = new TextView(); model.addObserver(view); view.update(model, null); view.addActionListener(this); Container c = getContentPane(); c.add(view); } public void actionPerformed(ActionEvent e) { JTextField t = (JTextField)e.getSource(); double r = Double.parseDouble(t.getText()); model.setRadius(r); } |
該程序是通過Java中的MVC模式編寫的,具有極其良好的可擴展性。它可以輕松實現(xiàn)以下功能:
1. 實現(xiàn)一個模型的多個視圖;
2. 采用多個控制器;
3. 當模型改變時,所有視圖將自動刷新;
4. 所有的控制器將相互獨立工作。
這就是Java編程模式的好處,只需在以前的程序上稍作修改或增加新的類,即可輕松增加許多程序功能。以前開發(fā)的許多類可以重用,而程序結(jié)構(gòu)根本不再需要改變,各類之間相互獨立,便于團體開發(fā),提高開發(fā)效率。
一個模型、兩個視圖和一個控制器
下面我們討論如何實現(xiàn)一個模型、兩個視圖和一個控制器的程序。當用戶在圖形化用戶界面輸入一個球體的半徑,程序除顯示該球體的體積與表面積外,還將圖形化顯示該球體。該程序的4個類之間的示意圖可見圖4。
圖4一個模型、兩個視圖和一個控制器的基本結(jié)構(gòu)
其中Model類及View1類根本不需要改變,與前面的完全一樣,這就是面向?qū)ο缶幊痰暮锰帯τ贑ontroller中的SphereWindows類,只需要增加另一個視圖,并與Model發(fā)生關聯(lián)即可。其關鍵實現(xiàn)代碼為:
public SphereWindow() { super(“Spheres: volume and surface area”); model = new Sphere(0, 0, 100); TextView tView = new TextView(); model.addObserver(tView); tView.addActionListener(this); tView.update(model, null); GraphicsView gView = new GraphicsView(); model.addObserver(gView); gView.update(model, null); Container c = getContentPane(); c.setLayout(new GridLayout(1, 2)); c.add(tView); c.add(gView); } |
其程序輸出結(jié)果見圖5。
圖5 輸出結(jié)果
一個模型、兩個視圖和兩個控制器
在上面的程序中,我們只能通過鍵盤輸入球體半徑,現(xiàn)在我們修改以上程序,利用鼠標放大、縮小右邊的球體圖形及可改變球體的半徑,從而獲得球體半徑的輸入。
此時的MCV模式為一個模型、兩個視圖和兩個控制器,其結(jié)構(gòu)可以見圖6,其UML類圖可以表示為圖7。
其中Sphere、TextView與GraphicsView類與前面完全一樣。在主程序SphereWindows中,該類這時不是直接作為Controller,它控制Controller1與Controller2的新建。該程序的關鍵代碼為:
public SphereWindow() { super(“Spheres: volume and surface area”); Sphere model = new Sphere(0, 0, 100); TextController tController = new TextController(model); GraphicsController gController = new GraphicsController(model); Container c = getContentPane(); c.setLayout(new GridLayout(1, 2)); c.add(tController.getView()); c.add(gController.getView()); } |
圖6一個模型、兩個視圖和兩個控制器的基本結(jié)構(gòu)
圖7 一個模型、兩個視圖和兩個控制器的UML類圖
當程序SphereWindow運行時,將鼠標移動到球體的外圓處,點擊拖動即可實現(xiàn)球體的放大與縮小,同時球體半徑、表面積與球體積也同時變化。
小結(jié)
從上面介紹可以看出,通過MVC模式實現(xiàn)與圖形用戶化界面相關的應用程序具有極其良好的可擴展性,是Java面向?qū)ο缶幊痰奈磥矸较颉?/P>