【說明】
引用了組里面的一架構師的文章,寫的很好的,尤其是偏于抽象的部分。希望對新手有用。
使用CommonNavigator開發資源管理器--模型篇
在基礎篇中,已經通過例子初步說明了,如何基于CNF制作一個簡單的資源管理器,但很多開發人員并不理解,樹上的結點是如何得到的,這就涉及到CNF的模型。在詳述CNF的模型之前,需要先對Tree所使用的模型進行描述。
對于早期習慣C/S開發的程序員來說,對于SWT中的Tree并不陌生,可以通過相應的TreeItem來創建子結點,但是這并不是一種好的設計和使用方式,它大大的增加了模型與UI之間的耦合度,所以在Swing中,使用了TreeNode來描述樹模型,而Eclipse則通過JFace提供了ITreeContentProvider接口來描述樹模型。這兩種方式有異曲同工之處,大家可以看一下這兩個接口,就會發現兩者非常之雷同,最大的區別在于前者通過userObject持有真實的數據,而后者則是由TreeItem的getData來持有,在使用的時候,才會由相應的TreeViewer傳給ITreeContentProvider,從結構來說,后者是一個純粹的控制類,而TreeNode則是更靈活一些,可以作為一個控制類,也可以作為一個模型體,所以相對而言,TreeNode更加靈活一些,但從本質上而言,兩者并無區別。
表面上看來,一個TreeViewer將會擁有一個ITreeContentProvider用來取得樹狀的數據模型,進而呈現出來,但CNF中的樹卻更加靈活,在基礎篇中,展現的圖中,卻表示可以通過擴展點org.eclipse.ui.navigator.navigatorContent來添加新的結點,而且這些與資源并沒有本質的關系,它可以與一個具體的文件或者目錄資源綁定,也可以與多個具體的文件或者目錄綁定,還可以是一個與文件或者目錄無關的模型。那么現在來看一下CNF到底做了哪些事情,使得它的模型擴展如此容易呢?
首先啟動Eclipse32.,然后創建一個新的工作區,再將CNF相關的代碼以插件的形式導入到這個工作區中,開始我們的分析過程。
講到這里,要提到Eclipse提供的一個接口IWorkbenchAdapter和IWorkbenchAdapter2,這兩個接口是有一點點怪的,因為從設計的角度來看,它將模型與展現層混合在一起,違反常見的設計準則,但從另一個角度來講,它可以減少用戶擴展的內容,有利于用戶開發。由此可見設計準則并不是一成不變的,很多時候,它也要在易用性和合理性方面做出適當的妥協。這一點也可以在我們自己的設計中加以考慮,設計并不是要偏向哪一個方向,恰恰相反,設計是要在多者之間,如易用性,穩定性,合理性之間取得一個平衡點,而不是在各方面都做到完美。
另外ITreeContentProvider有一個方法getParent(Object parent),它是用來為一個指定結點找到相應的父親結點,從而便于查找和定位,而這個方法卻被很多人所忽視,開發人員經常會習慣性的直接返回null,而且也不會出現什么錯誤,但這個方法其實卻是一個非常有用的方法,開發人員在使用Java資源管理器的時候,有一個經常使用的功能就是LinkWithEditor,這個功能經常是用來在資源管理器上定位當前打開的文件,這個功能如此之重要,以至于CNF專門為此定義了一個org.eclipse.ui.navigator.linkHelper來支持該功能。所以請根據實際情況,來實現這個方法,否則就無法正確的實現相應的功能。
以上對TreeViewer的模型進行了簡單的介紹和分析,接下來就看一下CNF是如何處理樹模型從而獲得如此高的靈活性。
CNF很好的利用了代理模式,它自身并沒有提供模型的能力,所以它將提供模型的能力仍然交給外部擴展點提供的類,它會根據當前要處理的結點,以及每個擴展點的表達式,來找出能夠處理當前結點的ITreeContentProvider實例,然后再將這些實例返回的子結點放入相應的Set中,最終以數組的方式返回給TreeViewer,從表面上來看,可能很難理解正常情況下,每個TreeViewer只有一個ITreeContentProvider的模型接口,如何能夠從多個實例中取得模型呢?就是由NavigatorContentServiceContentProvider這個代理類完成模型的組合功能。
因此只要提供自己的ITreeContentProvidre實現,然后通過擴展點掛入,即可將各種真實或者虛擬的模型掛入系統。
本博客中的所有文章、隨筆除了標題中含有引用或者轉載字樣的,其他均為原創。轉載請注明出處,謝謝!