以前的幾次帖子中,我們都談到了在UI平臺(tái)的設(shè)計(jì)過程中常常會(huì)使用的一種設(shè)計(jì)模式,就是封裝,但是封裝是一種極難把握的模式,而且,單單使用封裝往往也起不到任何設(shè)計(jì)效果,有時(shí)還會(huì)畫蛇添足,那么,大師們是怎么使用封裝的呢,我們看看Java領(lǐng)域的例子。
Swing是
由Sun的優(yōu)秀科學(xué)家和Netscape的杰出設(shè)計(jì)師共同創(chuàng)造出來的卓越的架構(gòu)。它一生下來就擁有皇族血統(tǒng),但注定一生都不會(huì)取得王位。現(xiàn)在崇拜
Eclipse設(shè)計(jì)架構(gòu)的人比較多(包括我),隨之而來的是對(duì)Swing的批評(píng)聲也很多(不包括我),其實(shí)這是一種錯(cuò)誤的認(rèn)識(shí),就像
Smalltalk是一種很優(yōu)秀但使用較少的語(yǔ)言,VB和Foxpro則屬于那種天生拙劣但使用廣泛的語(yǔ)言。Swing比Eclipse架構(gòu)早出來好幾
年,后者從前者那里吸取了不少的經(jīng)驗(yàn),也借鑒了很多模式,才會(huì)有今天的成就。而直到今天Swing仍然有很多值得我們學(xué)習(xí)的地方。
再說封
裝,打開JButton的源代碼就會(huì)發(fā)現(xiàn),JButton沒有往可憐的Windows界面上畫上任何一筆,換句話說,整個(gè)類里面一行繪圖代碼都沒有,這是
為什么?因?yàn)镴Button是一個(gè)Controller的變種,繪圖組件由另一個(gè)類提供,這個(gè)類以UI名字結(jié)尾,在內(nèi)部包中,且繪圖器在不同的界面風(fēng)格
下、不同的操作系統(tǒng)、甚至不同的語(yǔ)種下面有不同的實(shí)現(xiàn)。這使得JButton類四兩撥千斤,憑一個(gè)不變的框架同時(shí)實(shí)現(xiàn)了跨平臺(tái)和可插拔風(fēng)格。至于它的一些
顯示參數(shù),別著急,既然有C有V不可能沒有M啊,ButtonModel類負(fù)責(zé)維護(hù)JButton的參數(shù)。
我們?cè)倏醋吭降腅clipse,Eclipse比其這種封裝來說就要復(fù)雜的多了,我們分成六個(gè)環(huán)節(jié)來講。
1。Eclipse將Windows的繪制方法包裝成SWT,這種包裝很原始,但是很有效,因?yàn)镴ava不好調(diào)用Win32API,所以這一步實(shí)現(xiàn)了跨平臺(tái)。需要注意的是,這種包裝應(yīng)該屬于簡(jiǎn)單的分層,Eclipse編寫了一個(gè)操作系統(tǒng)的Facade,OS類,這個(gè)類的win32版的源代碼有2734行,顯然是個(gè)龐然大物啦。
2。Eclipse把SWT當(dāng)作它的基本組件來重用,(就好像這是別人寫的東西),它把SWT的組件繼續(xù)包裝成JFace,JFace采用真正意義上的 MVC模式,比起緊湊的SWT來要活潑一點(diǎn)。JFace把SWT當(dāng)成它的View,把Provider的實(shí)現(xiàn)當(dāng)作它的Model,把自己包里的可控的帶有組件邏輯的Viewer類當(dāng)成Controller。
3。由于SWT被設(shè)計(jì)用來繪制窗體組件,按照管理,應(yīng)該有一個(gè)包被用來繪制二維圖形,這個(gè)工作就交給Draw2D來完成,它被放置在GEF包中,和SWT 處在一個(gè)層次。需要注意的是,Draw2D與SWT的組織機(jī)制不同(見前面的文章)。
4。Eclipse繼續(xù)封裝,因?yàn)镴Face只解決了高級(jí)組件的問題,并不能直接放在Workbench里面用,所以Eclipse制作了Workbench包,這個(gè)包把Viewer封裝成ViewPart,它認(rèn)為Viewer是繪制器,而ContentProvider是Model,所以,像之前的幾次一樣,ViewPart變成了Controller。
5。有了ViewPart也就有了EditorPart,這兩種Part都有可能要顯示Form表單(一
種類似HTML的界面),表單上的控件——理所當(dāng)然,是由
SWT實(shí)現(xiàn)的——與一般意義上的控件有很大的不同,這種不同主要體現(xiàn)在展現(xiàn)方式和事件通知上。Eclipse采取的方式是另做一套內(nèi)部實(shí)現(xiàn),包裝SWT實(shí)
現(xiàn),比如SWT有一個(gè)Button,表單包也有一個(gè)表單Button,與Button通過一個(gè)Toolkit類轉(zhuǎn)換。這種方式就是設(shè)計(jì)模式中提到的
Proxy。
6。現(xiàn)在我們?cè)倏纯葱枰L二維圖的EditorPart,這個(gè)部分是通過GEF來實(shí)現(xiàn)的,GEF是比JFace和Workbench更嚴(yán)格的MVC,它再EditorPart的基礎(chǔ)上再包裝一次,將策略等控件業(yè)務(wù)與控件繪制分離。
今
天我得到的最重要的一個(gè)結(jié)論,就是封裝是相對(duì)的,MVC也是相對(duì)的,因此在JFace看來是Controller的東西在Workbench來看可能是
View,這可能導(dǎo)致在設(shè)計(jì)時(shí)的大量爭(zhēng)議。今天的另一個(gè)收獲是發(fā)現(xiàn)了封裝也有幾類,我能想到的應(yīng)該有Facade封裝、Proxy封裝、MVC封裝三種,
你還能想到更多的嗎?
做軟件的泡泡