2011-12-03 82 views
5

它在設計模式說 - 可複用面向對象軟件的元素書:橋樑模式 - 在Java中編譯的好處?

在情況下,只有一個實現(一個對一個),創建一個 抽象實施者類是不這是一個退化案例 的橋樑模式; 抽象和Implementor之間有一對一的關係。但是,當一個類的實現改變不會影響其現有客戶端 時,這種分離仍然是 ,也就是說,它們不應該被重新編譯爲 ,只是重新鏈接。

我懷疑編譯時間的好處,因爲我無法想象Java中的實現更改使其重新編譯其超類(本例中爲抽象)的情況。

例如,如果我們有X Y延伸,並在客戶端做:

Y y = new X(); 

在X的變化並不意味着y的重新編譯(當然,如果我們不希望改變方法簽名X

的)正是使用橋接模式時,同樣的事情:

YAbstraction yabstraction = new YRefinedAbstraction(new XImplementor()); 

在XImplementor的變化並不意味着YAbstraction的重新編譯。

所以,據我所知,這種好處不會發生在Java和一對一=>不需要橋接模式。

也許在其他語言中重新編譯子類強制超類的更改?像SmallTalk和C++一樣?

您的意見是什麼?

回答

3

在橋接模式中,您有兩個類層次結構:一個用於抽象(例如,帶有派生類,如DialogWindow和IconWindow的Window),另一個用於實現者(例如帶有派生類,如XWindowImpl和PMWindowImpl的WindowImpl)。實現者的接口應該隱藏於抽象的客戶端。通常,Implementor提供低級原語,Abstraction根據這些原語構建更高級別的操作,因此在分層次良好的系統中,客戶端不需要看到Implementor提供的低級接口。如果有一天,事實證明,由WindowImpl提供的接口不足以容納新的XYZWindowImpl,您保留自由改變它,因爲WindowImpl不應該直接由客戶端使用,而只能由Window及其子類使用。因此,WindowImpl的接口中的更改可能需要對Window進行修改,但不會傳播到客戶端。此外,人們常常將執行器隱藏在用於配置橋的抽象工廠的後面。

您描述的Bridge模式的優點取決於從抽象的客戶端隱藏Implementor的接口。在C++中,您可以通過簡單地不提供頭文件輕鬆地隱藏Implementor的界面。在Java中,您可以使實現者成爲包私有成員的抽象類。

在C++中,抽象的客戶端不需要重新編譯,只需要重新鏈接。在Java中,而不是鏈接你有類加載,因此所有你需要做的是重新加載應用程序與新的設置和一個新的jar文件。

想象一下,例如,抽象工廠使用命令行選項或環境變量來配置具有正確種類的ConcreteImplementor的橋時的情況。在這種情況下,您只需使用新的命令行/環境設置以及包含新的ConcreteImplementor的新jar文件來重新加載應用程序。您可以在不重新編譯客戶端代碼的情況下執

因此,爲您的問題提供直接的答案:在Java中,Bridge模式確實具有問題中描述的優勢。可能更大的程度上,如果你指望沒有發生過重新鏈接的事實。

+0

OP的觀點特定於實現者類只有一個實現的情況。 –

+0

感謝這個發展良好的解釋:)所以我總結:WindowImp中的更改只會引發Window中的更改並且不需要重新編譯客戶端=>因爲只有Window類的方法體被更改(以適應新的WindowImp)而不是Window Class的方法簽名,對嗎? – Mik378

+0

@ Mik378是的,沒錯。 –

0

Java沒有像C/C++一樣的「鏈接」。但是,我認爲這個概念仍然適用:如果實現類位於抽象的獨立庫(.jar文件)中,那麼您不必重新打包包含抽象的.jar文件。這可以簡化複雜系統的維護。

+0

好的,但與X,Y示例有什麼區別:如果Y在A.jar中,並且X在B.jar中,重新包裝X並不意味着重新包裝Y,您同意嗎? – Mik378

+0

@ Mik378 - 我同意這一點。我認爲在只有一種可能的實施情況下,整個模式只有很小的優勢(如果有的話)。我想到的想法是(抽象的)實現者類將與抽象類打包在一起,而具體的實現者或類將在單獨的.jar文件中。 (請注意,「抽象類」!=「抽象類」,不幸的是,這裏的術語有點令人困惑,但這就是GoF遺留給我們的東西。) –

+0

是的,我知道設計概念的抽象類是不一樣的概念在Java中都是抽象類。對於沒有橋樑模式的情況,我使用術語「抽象類」,它表示一個簡單的層次結構。 – Mik378