Draw2D--1. 設計思想和相關模式

- 中國WEB開發者網絡 (http://www.webasp.net)
-- 技術教程 (http://www.webasp.net/article/)
--- Draw2D--1. 設計思想和相關模式 (http://www.webasp.net/article/23/22112.htm)
-- 作者:未知
-- 發佈日期: 2005-04-30
1.  Draw2d 設計思想 Draw2d是一個宿主在SWT Composite控件中的輕量級的構件(widge)系統。一個Draw2d應用程序由一個 SWT Composite控件, 一個輕量級系統, 以及其內容(figures)組成。Figures是Draw2d的建造塊。下面的“Hello World”例子程序演示了如何實現一個最簡單的draw2d程序。Listing for "Hello World"

import org.eclipse.swt.widgets.Shell;

import org.eclipse.swt.widgets.Display;

import org.eclipse.swt.SWT;


 
import org.eclipse.draw2d.*;

import org.eclipse.draw2d.geometry.*;


 
public class HelloWorld {

         public static void main(String args[]){

                 Shell shell = new Shell(); 

                 shell.open();

                 shell.setText("Draw2d Hello World");

                 LightweightSystem lws = new LightweightSystem(shell);   

                 IFigure label = new Label("Hello World");

                 lws.setContents(label); //設置內容

                 Display display = Display.getDefault();

                 while (!shell.isDisposed ()) {

                          if (!display.readAndDispatch ())

                                   display.sleep ();

                 }

         }

}

運行這個程序的結果如下: 在上面例子程序的背後究竟發生了什麼呢?先看下面的Draw2d設計圖:



 
 
LightweightSystem是Draw2d的粘合劑。開發人員提供SWT composite和想要繪製的figure層次的根,然後LightweightSystem用默認值啟動剩餘的過程。LightweightSystem依賴Canvas,並含有一個EventDispatcher和一個UpdateManager。LightweightSystem本身是一個事件監聽器,能夠監聽多種事件。在將Canvas傳遞給LightweightSystem(通常通過LightweightSystem的構造函數)時,LightweightSystem就將自身作為監聽器註冊到Canvas,當Canvas產生各種LightweightSystem感興趣的事件後,作為監聽器,LightweightSystem中定義的方法會被調用。在LightweightSystem中定義的各個監聽器方法中,要將來自於SWT的事件轉換成draw2d事件並通過EventDispatcher將draw2d事件分配到當前被選中的圖形元素Figure。每個圖形元素Figure都可以作為監聽器容器。
 
SWT是IBM開發的一套GUI組件,與java中的SWING是同一類東西,只不過開發商不同罷了。在SWT中有一個名位Canvas的類,這個類是一個控件,根據它的名字,顧名思義,它是為繪圖提供繪圖表面;它引發各種鼠標事件和鍵盤事件,它是一個監聽器容器,可以將它引發的交互事件發送給感興趣的監聽器。LightweightSystem是draw2d中一個非常重要的類,它是draw2d能夠運行的調度中樞,這個類的主要作用是:1,  持有Canvas控件的引用。2,  使自身成為交互事件監聽器,並將自身註冊到Canvas中;當Canvas中引發各種交互事件時,使得LightweightSystem能夠得到通知。3,  持有事件轉發器。當LightweightSystem從Canvas中獲得交互事件通知後,它直接將該事件轉交給事件轉發器,事件轉發器首先將系統事件轉換成draw2d自定義的內部事件,然後根據draw2d的狀態對該事件進行分發。4,  持有更新管理器。當Canvas無效並要求重繪時,LightweightSystem會從來自Canvas的重繪事件中獲取無效矩形區域並請更新管理器更新該無效矩形區域;當draw2d中的某個圖形元素無效時,draw2d也會請更新管理器更新無效的圖形元素。但是,圖形元素無效與控件無效是兩個概念;當控件無效時,控件會引發OnPaint事件;當圖形元素無效時,系統並不會引發OnPaint事件。5,  持有根圖形元素(RootFigure)。根圖形元素在draw2d中有著非常重要的地位和作用,瞭解根圖形元素的地位和作用,對於瞭解draw2d是非常重要的。根圖形元素完全覆蓋在Canvas上(與canvas的工作區域的大小一樣大),它的背景色決定了應用程序的背景色。根圖形元素處於圖形元素樹型層次的最頂端,它只有一個孩子,這個孩子就是要顯示的內容。

 Draw2d中另一個非常重要的接口是IFigure, 它表示圖形元素抽像,所有的可以用圖形顯示的東西都要實現這個接口。Figure是IFigure的基本實現。Figure類的設計,涉及到一個非常著名的模式:Composite模式。 在Draw2d中,Figure中的所有的坐標都是int型的,沒有使用float或double類型。我當時也是非常奇怪,但仔細想想,其實也是可以理解的,至於具體原因,我會在以後的文章中詳細解釋。 Draw2d只提供了顯示模型的視圖類,並沒有提供與編輯相關的任何功能;如果開發人員打算開發一個不需要對模型執行編輯的圖形顯示軟件,那麼使用draw2d是合適的;如果要執行編輯動作,就需要同時使用GEF和draw2d了。 

 2. 幾個相關模式 2.1 MVC模式 提到MVC模式,幾乎所有的開發人員都會說,我知道,它不就是“模型-視圖-控制器”嗎?都知道,M表示Model, V表示視圖,C表示Controller。模型要負責提供數據,視圖要負責呈現模型(通常用圖形元素表示模型中的數據),控制器要負責創建圖形元素並修改模型。確實如此,說起來,MVC是一個很簡單的東西,不就是把數據、圖形、控制分開嗎?但說起來容易,做起來可就不容易了。在具體做程序時,通常的情況是,模型、視圖和控制器是三位一體的,往往是一個類表示三個東西。一個類既是模型,也是視圖,也是控制器。在draw2d中,大量使用了模型-視圖的概念,但沒有控制器,因為draw2d庫的主要目的是顯示模型,至於如何編輯模型是GEF的職責,如何定義模型並將模型映射到draw2d上是應用軟件開發人員色職責。在draw2d中定義的所有從Figure派生的圖形元素都是視圖類,它們都是用來呈現模型的;當同GEF一道使用draw2d時,就能體會到draw2d中的“Figure是視圖”這個概念的含義。設計一個基於MVC的應用框架相對於設計一個基於MVC的類層次,要難得多;將編輯和顯示獨立到框架中的不同層上需要高超的設計水平。GEF和draw2d就是基於MVC設計的應用框架,GEF是控制層,draw2d是顯示層。關於GEF,我會在以後的文章中介紹,GEF的設計非常精彩。我對draw2d中的一個模型—視圖設計印象非常深:範圍模型和滾動條。對一個滾動條而言,它涉及到:最小範圍,最大範圍,當前值, thumb的大小,頁增量。在draw2d中,定義了一個接口RangeModel表示這些數據,並且是一個監聽容器。滾動條持有範圍模型,並將自身作為監聽器註冊到範圍模型中。當滾動條發生滾動時,它會修改範圍模型,然後範圍模型再通知其它對範圍模型數據變化感興趣的外部對像;當範圍模型的數據被外部對像改變之後,它就通知滾動條改變自身的顯示以保持與範圍模型的數據相一致。在以後的文章中,我會重點介紹視口,視口就非常精彩地使用了範圍模型來與滾動條通信並保持同步。需要指出的是,這裡介紹的滾動條實際上是視圖和控制器地合成體,它是視圖和控制器二者功能的合併。在draw2d中,MVC設計模式比較多。 
 
2.2 Composite模式 draw2d中的圖形元素類層次採用Composite模式。用IFigure表示圖形元素抽像,用Figure表示IFigure的基本實現並包含IFigure接口。Composite模式的動機是:將對像組合成樹形結構以表示“部分-整體”的層次結構,Composite使得用戶對單個對象和組合對象的使用具有一致性。在.Net中的GUI控件庫就是採用的Composite設計模式,因為各種控件之間存在明顯的部分與整體關係,例如Form類從Control派生,但很明顯它又是一個控件容器,可以包含各種控件。draw2d是一個輕量級的widget構件系統,它提供了幾乎與常用的控件對等的各種圖形元素構件(例如按鈕、滾動條)等;但這些圖形元素構件不是控件,它們緊緊只是從Figure派生的圖形元素,這也是draw2d被稱之為輕量級widget系統的原因。因為draw2d是一個構件庫,而構件本質上就存在著“部分-整體”關係,所以draw2d中的圖形元素也就自然而然的採用了Composite模式。因為採用了Composite模式,所以在一個基於draw2d應用程序中,圖形元素是呈樹狀的,嚴格來說,一個應用程序中只存在一個圖形元素,這個圖形元素就代表應用程序要顯示的內容(稱之為內容圖形元素);內容圖形元素可以包含孩子,孩子又可以包含孩子……,子孫無窮盡也。                    Draw2d圖形元素設計圖  2.3 觀察者模式這個模式在Java中已經被提升到了一個很重要的位置,以至於Java類庫都直接支持它。Java中的事件處理機制就是基於觀察者模式實現的,因為draw2d是一套輕量級的widget構件系統,所以圖形元素能夠引發事件,也能夠接收事件。


webasp.net