在物件導向技術中,介面(Interface)概念是很重要的一項技術。我個人認為透過介面技術,可以讓我們獲得下列兩項好處:

第一,設計出以服務為導向的系統,充分展現出以客為尊的貼心。介面像契約,它是一種服務概念,有別於傳統物件的實體概念。因此,一個類別可以同時間實作多個介面,對客戶端(Client)提供多項服務。

第二項好處是降低物件之間的相依程度,可以大幅降低汰舊換新的成本。介面與實作客戶端使用介面、依賴介面,而不是直接依賴類別,因此遇到需要汰舊換新時,可以在不影響客戶端的情況下,更新真正提供實作的類別。

具體來說,一個介面將宣告(declare)一組能見度為公開的屬性和操作。一個介面就像一份合約,它記錄了一組關係緊密的公開特徵和契約,使用該介面的物件可以得到介面上所約定的服務,而實作該介面的物件則必須提供介面上所約定的服務。請你看到圖1的範例,客戶端可以透過I訂報介面,執行學員的訂閱電子報或取消訂閱的操作。

圖1 介面與實作類別

眼尖的你可能已經發現介面的圖示,好像跟類別圖示一樣,都是矩形。而且,你如果把矩形打開來看,會發現跟類別圖示一樣是三格矩形,唯一的差別只是在介面名稱上方有標示《interface》字眼,如圖2所示。

圖2 介面與類別圖示

介面和類別都採用矩形圖示,那是因為它們繼承同一個父類別,也就同時繼承了矩形圖示了,如圖3所示。特別要說明的是,有些人以為介面只能定義一組公開操作,不能定義屬性,其實你要是看到圖3的UML母模,就可以清楚得知介面其實也可以定義屬性的。

圖3 介面[UML母模]

圖4 訂報介面
不過,無論介面定義了屬性或操作,它們的能見度都必須是公開等級。也因此,我們要是為介面新增屬性或操作時,VS2010/UML會自動設定為公開能見度,如圖4所示。

所以,請你打開介面屬性和操作的性質表查看一下,會發現兩者的能見度都自動設定為「公開」(Public),而且出現了不能更改的反白字樣,如圖5所示。

圖5 公開能見度

圖6 公開能見度
仔細看圖4的介面操作,不僅是公開操作,而且是抽象操作。請看到圖6,我們打開介面操作的性質表查看一下,會發現操作被設定為抽象操作,而且這項設定一樣是反白,不讓我們更改。

我推想,這可能是VS2010/UML不想讓介面誕生個體,所以才會自動設定為抽象操作。在UML中,介面確實不能誕生個體,但是卻沒有規定操作一定要設定為抽象操作。不過,換個角度來看,VS2010/UML這樣設定也沒錯啦,因為介面操作僅有宣告,並沒有實作內容,而這樣的操作確實也是抽象操作。

圖7 介面的性質表
歸納說起來,介面具備有下列三項重要的特性:

1. 介面只是一種宣告,沒有實作內容,所以無法被個體化。換句話說,在系統執行期間(run-time),介面不能誕生個體,當然也沒有所謂的介面個體。

2. 介面宣告的屬性和操作,其能見度一定都是公開等級。

3. 介面可以宣告公開屬性,但實作物件不一定得擁有相同的屬性,實作物件只要能夠提供此屬性即可。

最後,請你也跟我一塊打開介面的性質表來查看一下,除了樣版概念外,其餘的小性質我們以前都談過了,就不再重述了,如圖7所示。

圖8 介面縮圖
對了,差點忘了,介面圖示有另一種縮圖,就是常見的棒棒糖狀的空心小圓,如圖8所示。

你只要點選介面和實作類別之間的實作關係,再點選像確認表格的小圖,就會出現簡易的選單,請選擇「棒棒糖顯示」(Show as Lollipop)的選項,如圖9所示。

圖9 棒棒糖顯示

一般來說,在類別圖面上顯示介面時,我們可以選用矩形圖示或小圓縮圖,二擇一。

不過,我發現VS2010/UML不是二擇一,它會同時出現兩個介面圖示。如果,我們選擇移去圖8中的介面矩形圖示,或者介面小圓縮圖,任一個圖示時,I訂報介面就會被移除掉。這樣的操作設計有點奇怪,只好等看看VS2010/UML後續的改版,會不會把這個操作稍微修改一下了。介面實現
前面我們還留了一個「介面實現」(Interface Realization)沒談,這條介面實現關係出現在介面與實作類別之間,是一條帶大三角形箭頭的虛線,如圖10所示。

圖10 介面實現

介面實現關係的名稱有變動過,在2003年UML2.0草版規格書中,這條關係線叫做「實作關係」(Implementation),如圖圖11所示。但是,到了2005年UML2.0正式版時,這條關係線就改名為現在的「介面實現」(InterfaceRealization)了,如圖12所示。

圖11 實作關係[UML2.0-2003]

圖12 介面實現[UML2.0-2005]

不過,介面實現的圖示倒是沒變過,一直都是帶大三角形箭頭的虛線。特別提到它的名稱變動,主要是因為UML官方的初級認證考試大量參考2003年的UML規格書,如果你有意思參加初級認證考試的話,稍微注意一下,總是比較妥當。

圖13 繼承與連接線
接著,請你看到VS2010/UML類別圖的工具箱中,並沒有一個叫做介面實現的圖示可選。你可以使用兩種方式新增介面實現,一個是使用繼承關係,另外一個是使用智慧型的連接線,如圖13所示。

再看到圖14,其實在VS2010/UML中有提示說明繼承關係可以兩用。我猜想,這或許也是VS2010/UML不用「一般化關係」這個詞彙,而寧可採用「繼承關係」的原因之一,因為這樣可以共用工具箱中的工具,透過VS2010/UML智慧判斷,降低工具箱的複雜度。

圖14 繼承或實現

圖15 一般化關係與介面實現[UML母模]
針對VS2010/UML的工具箱圖示共用以及智慧判斷,這兩項特色,確實大量降低了UML原先一堆瑣碎圖示的數量及複雜度,讓開發人員不需要懂太多、太深入,就可以立即上手。我想這一直是Visual Studio的使命之一,也一直是Visual Studio的強項,如圖15所示。

不過,回到VS2010/UML讓繼承關係,成為一般化關係和介面實現雙用的這項特色上,我個人覺得立意雖佳,但是總覺得有一點小小的不妥。請你看到圖15,介面實現是依賴關係(Dependency)的一種,依賴關係的圖示是帶開放性箭頭的虛線。而一般化關係的圖示是採用帶大三角形實線,一般化關係與依賴關係屬於平輩、手足。怎麼會讓介面實現共用一般化關係的帶大三角形實線呢?我個人是感覺有點不妥啦,但是這是小細節啦,不打緊,你可以不把這點放在心上。

圖16 介面實現的性質表
接著,請你打開介面實現的性質表查看一下,如圖16所示,沒有特別的小性質需要解釋的。打開介面實現的模版來看,出現了三個模版,我們以前沒見過的。由於,這幾個模版會牽扯到其他概念,所以我們稍後才來細談。依賴關係
先回顧一下依賴關係的概念,我們在用例圖的章節中,曾經提到過依賴關係。那時我們提到幾點:

● 依賴關係雖然是個常見的初級概念,但是比較常用在其他的UML圖款中,譬如用在類別圖中,總之比較少用在用例圖中。

VS2010/UML在用例圖工具箱中提供這兩個元素,似乎只是想讓開發人員可以用依賴關係來連接用例和用例敘述,如圖17所示。

圖17 產出物與依賴關係

● 依賴關係的圖示是帶箭頭虛線,連接了「依靠元素」(depending element)和「供應元素」(supplier element)兩端,並且由依靠端連接指向供應端,代表依靠端在語意上或結構上不完整。具體來說,依靠端為了自身的規格或實作,因而必須依賴供應端,如圖18所示。

圖18 依賴關係

當時只有簡單介紹一下依賴關係,其實依賴關係還有很多細部概念,現在剛好可以回過頭來,再對它多探究一些。

在類別圖中,最常用到依賴關係的情況是,用來連接客戶端類別與供應端介面,如圖19所示。特別提醒你,連接實作類別與介面之間的是「介面實現關係」,而介面與使用類別之間的關係則是「依賴關係」。

圖19 依賴關係

圖20 依賴關係的性質表
接著,我們打開依賴關係的性質表查看一下,很乾淨,看起來沒有什麼需要特別說明的小性質,如圖20所示。

再者,這裡有個小地方要釐清。在UML規格書中,介面與使用類別之間的依賴關係,不是一般的依賴關係,其實是一種比較特別的依賴關係,稱為「使用依賴」(Usage Dependency)。

請你看到圖21的UML母模,依賴關係有很多種,之前我們在用例圖中使用的是一般的依賴關係,介面和實作類別之間的是介面實現,而介面與使用類別之間的是使用依賴。

圖21 依賴關係[UML母模]

不過,實務上經常沒有特別標示使用依賴,就直接使用一般的依賴關係。這其實也無妨,這邊提出來,只是想要趁這個機會讓你知道UML規格中的標準定義。

由於,依賴關係往下細分成多種,對於初學者是個不小的困擾,因為實在不容易區分。所以,此處我們特別把它們各自的特色點出,希望對你有所幫助,條列如下:

● 依賴關係(Dependency):客戶端(Client)為了自身的「規格」(Specification)或「實作」(Implementation)依賴供應端(Supplier),如圖22所示。

圖22 依賴關係

● 使用關係(Usage):客戶端不會指出如何使用供應端,僅透過自身的「定義」(Definition)或「實作」(Implementation)來使用供應端。請看到圖23的例子,這是UML規格書中的範例,標準的使用關係圖示是在依賴關係的帶箭頭虛線旁邊標示出《use》模版。不過,VS2010/UML不讓我們自行新增模版,僅能挑選已提供的模版,所以我只好把《use》當成依賴關係的名稱來處理。

圖23 使用關係[UML規格書]
● 抽象關係(Abstraction):抽象關係比較特別,它用來連接「同一個概念」(the same concept)。但是,這個概念被分裂成兩個不同抽象程度的元素,或者兩個不同觀點下的元素。比方說在圖24中,「Student」和「學員」是相同的概念,但前者是設計層級的類別(design-level class),而後者則是分析層級的類別(analysis-level class)。

圖24 抽象關係

圖25 實現關係[UML規格書]
● 實現關係(Realization):實現關係是一種特殊的抽象關係,所以我們可以基於「相同概念、不同抽象層級或不同觀點」(原本的抽象關係),再進一步特殊化。所以,我們可以這麼說,實現關係兩端的元素屬於同一個概念,但客戶端代表概念的實作,供應端則代表概念的規格。請看到圖25,這是UML規格書中的範例,意謂著供應端:業主(Owner)和員工(Employee)兩類別的組合,實現了客戶端:企業(Business)。不過,這個圖是我用StarUML畫出來的,VS2010/UML不讓我在兩類別之間建立實現關係。

● 介面實現(InterfaceRealization):特殊的實現關係,用於類詞(Classifier)和介面(Interface)之間,一般我們用於實作類別與介面之間,如圖26所示。

圖26 介面實現

圖27 介面實現性質表的模版
在談了這麼多之後,我們現在再回過頭來看介面實現性質表中的三個模版,就比較能夠理解了,如圖27所示。

其實,你要是打開UML規格書來查看一下,立即就會發現這三個模版原先屬於抽象關係所有,只不過介面實現繼承了這三個模版,如圖28所示。

圖28 抽象關係的三個模版[UML規格書]

所以,最後,我們就來看看抽象關係的這三個模版吧,條列說明如下:

● 衍生(derive):客戶端依賴供應端,衍生計算出,兩者間可以放置衍生關係。例如圖29的範例中,優惠價是由定價乘上折扣,計算出來的,所以兩者間為衍生關係。

圖29 衍生

● 改良(refine):改良關係沒什麼特別的地方,就是字面上的涵義,客戶端改良供應端,經常用在設計元素(客戶端)與分析元素(供應端)之間。實務上,其實鮮少使用這個模版,實在舉不出什麼合適的例子,所以我就不特別舉例了,如圖30所示。

圖30 改良

在2003年的UML2草版規格書中,曾經舉過一個例子,如圖31所示。不過,後來可能覺得這個例子有誤,所以在2005年的UML2正式版規格書中,就摘掉這個例子了,而且也就留空,沒有再補上其他例子。這個例子確實造成誤解,仔細理解,你會發現關係線的方向性剛好跟前面所談的相反。

圖31 改良抽象的例子[UML2.0-2003]

● 追溯(trace):追溯模版大概是這三個模版中稍微常見到的一個,它用於不同模式(model)中的相同概念。所以,在圖32的範例中,「Student」屬於設計模式,但是「學員」位於分析模式,兩個概念相同,但是位於不同模式中,透過追溯關係可以追溯兩者的變動。老實說,我在實務上沒用過追溯模版,也不常在書籍或文章中看到。前些時候剛好在Ivar Jacobson大師的《Aspect-Oriented Software Development With Use Cases》一書,看到跟追溯模版有關的範例,我隨手摘錄了書中的兩個範例圖,不加以說明,只是想讓你看看Ivar Jacobson大師曾經這樣使用追溯模版,如圖33圖34所示。

圖32 追溯

圖33 追溯的範例一[Jacobson-圖11-5]

圖34 改良抽象的例子[UML2.0-2003]

到這邊,我們已經將UML類別圖基礎概念介紹完了,複習一下,這些基礎概念包括了類別、關係、以及這一回的介面。在類別概念中則進一步談到靜態資料所抽象形成的屬性,及其行為所抽象化的操作,這是類別中最重要的兩個組成元素。再來,因為單獨的類別無法提供太大的功用,必須透過關係連結其他的類別,所以,我們也介紹了結合關係、聚合關係、組合關係,以及VS2010所謂的繼承關係,也就是UML中的一般化關係。最後,介紹完介面後,下一回將進入類別圖的高級概念。

專欄作者

熱門新聞

Advertisement