Gef與MVC體系結構

xyz發表於2010-10-19


摘要:本文首先介紹了標準的MVC體系構架,同時也介紹了最常見的一類綜上所述,在gef框架中,使用者編輯請求的相應過程如下MVC模式的變種。之後,文章重點介紹了MVC結構在gef框架中的體現與應用,以及gef是如何綜合利用工廠模式、命令模式等設計模式來輔助MVC結構的實現。例如gef成功利用命令模式分擔了控制器的部分責任。
前言
GEF全稱Graphical Editor Framework。它是一個基於eclipse的圖形化編輯框架。透過它,開發人員可以方便的以圖形化的方式(而非文字的方式)展示和編輯模型。GEF是一種很有價值的工具,很多著名的應用都採用了gef框架,其中包括現在最流行的開源工作流jbpm的定製工具。Gef是按照標準的mvc模式實現的,其中還使用到了工廠模式、命令模式,Policy模式等一些設計模式。

MVC結構
MVC是"Model-View-Controller"的縮寫,即”模式-檢視-控制器"。MVC結構強制將一個應用分為模型層、檢視層以及控制器。透過三者之間的協調共同響應完成使用者的請求,即互動過程。
它們之間的協作關係如圖:
[img index=1]
上圖為mvc模式最標準也是最常見的一種形態。從上圖可以看出,模型與檢視不直接打交道,而是透過控制器,即控制器完全分離了檢視與模型。這是mvc模式的最大特點之一。
在現實開發中,由於實際需要,開發設計人員通常會對標準的mvc模式進行一些修改。屏棄其中的某些特性,而加入新的特性。其中最常見的變化形式如下圖所示:
[img index=2]
可以看到,控制器並沒有完全分離檢視與模型。即它不再負責根據模型修改檢視,這一過程是讓模型與檢視雙方“面對面”直接進行。這樣做雖然增強了檢視與模型之間的耦合,但是減輕了控制器的負擔。
另外,在通常情況下,為了進一步解耦合,層與層之間的資料透過一種叫做DTO即資料傳輸物件的介質進行傳遞。DTO的時間通常很簡單,只有若干屬性和屬性對應的get/set方法,是一個標準的純java物件,即pojo。例如基於mvc結構的struts中的actionFrom即為一個DTO。
檢視
檢視層的作用主要有兩個:
 接收使用者輸入,將輸入資訊傳遞給控制層。
 負責展示資料,它將模型層中的具體資料以一定的形式展示給使用者。
模型和檢視之間是一個多對多的關係,一個模型可以對應多個檢視,一個檢視也可以關聯多個模型。
控制器
控制層接收到檢視層傳遞過來的請求後,分析請求資訊,根據請求內容選擇相應的模型,並修改模型的具體數值。
同時當模型發生變化的時候,將會通知控制器,以更新檢視。
模型
模型是行為與狀態的雙重抽象,即封裝了資料與方法。當模型發生變化時,相應的檢視會根據新的模型資料重新繪製展現內容。
優點
使用mvc結構的應用有如下有點:
 便於分工。Mvc機構將程式分為’M-V-C’三層,這三層各司其職。這樣便於分工協作。例如,傳統結構的應用將業務邏輯和介面顯示混雜在一起,這樣美工很難對頁面進行美化。而mvc結構的應用,將應用分層,檢視層只有展現程式碼便於美工美化頁面。
 提高了程式碼的可重用性。多個檢視能共享一個模型,多個模型也能共享一個檢視,提高了程式碼的可重用性。
 便於維護更新,由於mvc的解耦合特性。使得維護和變更相對變得比較容易。因此可以方便地改變應用程式的業務資料和業務規則,遷移資料庫等等。不會牽一髮而動全身。

Gef中的mvc實現
Gef完全按照標準的mvc體系結構完成。
模型
Gef模型的規約十分寬泛——任何java類都可以作為gef的模型。也就是說,gef在模型層是非侵入式的。這一點使得gef的應用更加廣泛,靈活。
但是為了能夠讓控制器知道模型的變化,我們需要一種機制——讓模型發生變化的時候通知控制器。由於靈活性的需要,gef並沒有把這種機制實現在框架層。但是我們通常會在模型層中新增PropertyChangeSupport型別的成員變數,用來觸發事件,通知控制器。例如:
public class AbstractModel {
private PropertyChangeSupport listeners = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.addPropertyChangeListener(listener);
}
public void firePropertyChange(String propName, Object oldVal, Object newVal) {
listeners.firePropertyChange(propName, oldVal, newVal);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.removePropertyChangeListener(listener);
}
}
檢視
檢視是模型圖形方式的表現,它以某種方式展示模型。Gef是一個圖形編輯框架,所以gef的檢視主要是將模型以圖形化的方式顯示出來。雖然任何實現IFigure介面的類都可以作為檢視,但是GEF使用Draw2D可檢視形(figure)。Draw2d是SWT平臺上的圖形庫,你可以用它定製屬於自己的、不依賴於特定作業系統本地元件的上層元件。
那麼檢視又是如何顯示的呢。這要用到AbstractEditPartViewer,它負責將檢視安裝到同一個SWT Control上。
控制器
在gef中,控制器又稱為編輯部件,是模型和檢視之間的橋樑,也是gef最重要的部分。所有的Gef控制器都需要繼承EditPart類。
根據mvc體系結構,控制器的功能主要有兩個。
 監聽模型的變化,根據變化修改檢視。
 當使用者編輯檢視時,把編輯的結果反映到對應得模型中。
建立——工廠模式
Gef在控制器的生成中,使用了工廠模式。通常每一個模型都對應一個控制器,所以gef要求提供一個EditPartFactory,該物件負責透過給定的模型建立與之對應的控制器。
當模型被建立的時候,EditPartFactory將會被呼叫,建立出模型對應的控制器。
監聽模型變化
控制器需要監聽模型的變化,從而根據新的模型資料重新顯示檢視。那麼就需要將控制器註冊成為模型的監聽者。例如下面的程式碼
public void activate() {
if (isActive()) {
return;
}
super.activate();
((Node) getModel()).addPropertyChangeListener(this);
}
public void deactivate() {
if (!isActive()) {
return;
}
super.deactivate();
((Node) getModel()).removePropertyChangeListener(this);
}
方法activate的作用是當被啟用的時候,把自己註冊成為模型的監聽。Deactivate相反,當失活的時候,將自己從對應的模型的監聽者中刪除。
由於模型層使用了PropertyChangeSupport類,所以,控制器需要實現PropertyChangeListener介面。PropertyChangeListener要求實現propertyChange方法。
public interface PropertyChangeListener extends java.util.EventListener {
void propertyChange(PropertyChangeEvent evt);
}
當模型發生變化時,對應控制器的propertyChange方法將會被呼叫。要說明的是,在gef應用中,控制器通常負責根據模型資料修改檢視顯示,而非簡單的通知檢視重畫。
修改模型——策略與命令
當使用者進行編輯操作的時候,控制器還需要解析這些操作並修改相應的模型。這通常是一系列負責的操作,可能會使得控制器非常龐大。Gef透過進入請求編輯策略與命令模式很好大分擔了控制器的本身的負擔。也達到了解耦合的目的。其中編輯策略用於解析使用者編輯請求,命令用於修改模型。
同時引入命令模式的另外一個目的就是“回退”功能,一個好的圖形編輯器“回退”功能是必不可少的。命令模式透過“redo”和“undo”等操作可以很多好的支援“重做”以及“回退”的功能。
當控制器接收到使用者的編輯請求後,會根據請求物件中的角色資訊尋找處理該請求的編輯策略。要說明的是,編輯策略需要事先被註冊安裝到控制器中,並對應相應的角色。角色是gef框架抽象出來的一個標識。控制器EditPart就是透過角色標識找到處理請求的策略的。
編輯策略接收到請求後,分析請求資訊。根據分析的結果選擇建立相應的命令,並且初始化命令的相關引數。
由gef框架負責執行編輯策略產生的命令。命令將會修改相應的模型。同時gef框架會記錄下執行的命令,以備“重做”“後退”等功能使用。
使用者編輯請求響應過程
綜上所述,在gef框架中,使用者編輯請求的相應過程如下:
[img index=3]

1. 當使用者進行編輯操作時,gef框架將操作封裝成一個請求物件,並將其傳遞給控制器。
2. 控制器根據角色選擇相應的編輯策略處理請求。
3. 編輯策略分析請求資料,建立並初始化命令物件。
4. 命令執行的過程就是修改模型的過程。
5. 當模型被修改後,將會觸發事件,告知其監聽者——該模型對應的控制器。
6. 控制器根據模型資料修改檢視顯示。

結束語
Gef是一個完全基於MVC體系構架搭建的圖形編輯框架。正是MVC體系構架的進入,使得模型層與檢視層解耦合。那麼模型層的約束就得到了極大的解放。這意味著gef可以適用於更廣泛的業務。也正是MVC體系結構的進入,使得基於gef框架開發的應用結構更加清晰,更加有利於分工開發與後期維護。
同時gef引入了請求編輯策略與命令模式成功分解了gef控制層的負擔。其中命令模式的引入也使得應用支援“重做”“回退”等功能。

相關文章