<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    每日一得

    不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速開發
    最近關心的內容:SSH,seam,flex,敏捷,TDD
    本站的官方站點是:顛覆軟件

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      220 隨筆 :: 9 文章 :: 421 評論 :: 0 Trackbacks

    一、引子

    裝飾模式?肯定讓你想起又黑又火的家庭裝修來。其實兩者在道理上還是有很多相像的地方。家庭裝修無非就是要掩蓋住原來實而不華的墻面,抹上一層華而不實的涂料,讓生活多一點色彩。而墻還是那堵墻,他的本質一點都沒有變,只是多了一層外衣而已。

    那設計模式中的裝飾模式,是什么樣子呢?

    ?

    二、定義與結構

    裝飾模式( Decorator )也叫包裝器模式( Wrapper )。 GOF 在《設計模式》一書中給出的定義為:動態地給一個對象添加一些額外的職責。就增加功能來說, Decorator 模式相比生成子類更為靈活。

    ?????? 讓我們來理解一下這句話。我們來設計 這個類。假設你根據需求為 類作了如下定義:

    現在,在系統的一個地方需要一個能夠報警的 Door ,你來怎么做呢?你或許寫一個 Door 的子類 AlarmDoor ,在里面添加一個子類獨有的方法 alarm() 。嗯,那在使用警報門的地方你必須讓客戶知道使用的是警報門,不然無法使用這個獨有的方法。而且,這個還違反了 Liskov 替換原則。

    也許你要說,那就把這個方法添加到 Door 里面,這樣不就統一了?但是這樣所有的門都必須有警報,至少是個 啞巴 警報。而當你的系統僅僅在一兩個地方使用了警報門,這明顯是不合理的 —— 雖然可以使用缺省適配器來彌補一下。

    ?????? 這時候,你可以考慮采用裝飾模式來給門動態的添加些額外的功能。

    ?????? 下面我們來看看裝飾模式的組成,不要急著去解決上面的問題,到了下面自然就明白了!

    1) ??????? 抽象構件角色( Component ):定義一個抽象接口,以規范準備接收附加責任的對象。

    2) ??????? 具體構件角色 (Concrete Component) :這是被裝飾者,定義一個將要被裝飾增加功能的類。

    3) ??????? 裝飾角色 (Decorator) :持有一個構件對象的實例,并定義了抽象構件定義的接口。

    4) ??????? 具體裝飾角色 (Concrete Decorator) :負責給構件添加增加的功能。

    看下裝飾模式的類圖:

    圖中 ConcreteComponent 可能繼承自其它的體系,而為了實現裝飾模式,他還要實現 Component 接口。整個裝飾模式的結構是按照組合模式來實現的,但是注意兩者的目的是截然不同的(關于兩者的不同請關注我以后的文章)。

    ?

    三、舉例

    這個例子還是來自我最近在研究的 JUnit ,如果你對 JUnit 還不太了解,可以參考 JUnit入門》 、 JUnit源碼分析(一)》 、 JUnit源碼分析(二)》 、 JUnit源碼分析(三)》 。不愧是由 GoF 之一的 Erich Gamma 親自開發的,小小的東西使用了 N 種的模式在里面。下面就來看看 JUnit 中的裝飾模式。

    ?????? JUnit 中, TestCase 是一個很重要的類,允許對其進行功能擴展。

    ?????? junit.extensions 包中, TestDecorator 、 RepeatedTest 便是對 TestCase 的裝飾模式擴展。下面我們將它們和上面的角色對號入座。

    ?????? 呵呵,看看源代碼吧,這個來的最直接!

    ?????? // 這個就是抽象構件角色

    ?????? public interface Test {

    ?????? /**

    ?????? ?* Counts the number of test cases that will be run by this test.

    ?????? ?*/

    ?????? public abstract int countTestCases();

    ?????? /**

    ?????? ?* Runs a test and collects its result in a TestResult instance.

    ?????? ?*/

    ?????? public abstract void run(TestResult result);

    }

    ?

    // 具體構件對象,但是這里是個抽象類

    public abstract class TestCase extends Assert implements Test {

    ?????? ……

    ?????? public int countTestCases() {

    ????????????? return 1;

    ?????? }

    ?????? ……

    ?????? public TestResult run() {

    ????????????? TestResult result= createResult();

    ????????????? run(result);

    ????????????? return result;

    ?????? }

    ?????? public void run(TestResult result) {

    ????????????? result.run(this);

    ?????? }

    ?????? ……

    }

    ?

    // 裝飾角色

    public class TestDecorator extends Assert implements Test {

    ?????? // 這里按照上面的要求,保留了一個對構件對象的實例

    ?????? protected Test fTest;

    ?

    ?????? public TestDecorator(Test test) {

    ????????????? fTest= test;

    ?????? }

    ?????? /**

    ?????? ?* The basic run behaviour.

    ?????? ?*/

    ?????? public void basicRun(TestResult result) {

    ????????????? fTest.run(result);

    ?????? }

    ?????? public int countTestCases() {

    ????????????? return fTest.countTestCases();

    ?????? }

    ?????? public void run(TestResult result) {

    ????????????? basicRun(result);

    ?????? }

    ?????? public String toString() {

    ????????????? return fTest.toString();

    ?????? }

    ?????? public Test getTest() {

    ????????????? return fTest;

    ?????? }

    }

    ?

    ?????? // 具體裝飾角色,這個類的增強作用就是可以設置測試類的執行次數

    public class RepeatedTest extends? TestDecorator {

    ??? private int fTimesRepeat;

    ?

    ??? public RepeatedTest(Test test, int repeat) {

    ?????????? super(test);

    ?????????? if (repeat < 0)

    ????????????????? throw new IllegalArgumentException("Repetition count must be > 0");

    ?????????? fTimesRepeat= repeat;

    ??? }

    ??? // 看看怎么裝飾的吧

    ??? public int countTestCases() {

    ?????????? return super.countTestCases()*fTimesRepeat;

    ??? }

    ??? public void run(TestResult result) {

    ?????????? for (int i= 0; i < fTimesRepeat; i++) {

    ????????????????? if (result.shouldStop())

    ???????????????????????? break;

    ????????????????? super.run(result);

    ?????????? }

    ??? }

    ??? public String toString() {

    ?????????? return super.toString()+"(repeated)";

    ??? }

    }

    ?????? 使用的時候,就可以采用下面的方式:

    TestDecorator test = new RepeatedTest(new TestXXX() , 3);

    讓我們在回想下上面提到的 的問題,這個警報門采用了裝飾模式后,可以采用下面的方式來產生。

    DoorDecorator alarmDoor = new AlarmDoor(new Door());

    ?

    ?

    四、應用環境

    ?????? GOF 書中給出了以下使用情況:

    1) ??????? 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。

    2) ??????? 處理那些可以撤消的職責。

    3) ??????? 當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。

    來分析下 JUnit 的使用是屬于哪種情況。首先實現了比靜態繼承更加靈活的方式,動態的增加功能。試想為 Test 的所有實現類通過繼承來增加一個功能,意味著要添加不少的功能類似的子類,這明顯是不太合適的。

    而且,這就避免了高層的類具有太多的特征,比如上面提到的帶有警報的抽象門類。

    ?

    五、透明和半透明

    ?????? 對于面向接口編程,應該盡量使客戶程序不知道具體的類型,而應該對一個接口操作。這樣就要求裝飾角色和具體裝飾角色要滿足 Liskov 替換原則。像下面這樣:

    Component c = new ConcreteComponent();

    Component c1 = new ConcreteDecorator(c);

    JUnit 中就屬于這種應用,這種方式被稱為透明式。而在實際應用中,比如 java.io 中往往因為要對原有接口做太多的擴展而需要公開新的方法(這也是為了重用)。所以往往不能對客戶程序隱瞞具體的類型。這種方式稱為 半透明式 。

    java.io 中,并不是純裝飾模式的范例,它是裝飾模式、適配器模式的混合使用。

    ?

    六、其它

    采用 Decorator 模式進行系統設計往往會產生許多看上去類似的小對象,這些對象僅僅在他們相互連接的方式上有所不同,而不是它們的類或是它們的屬性值有所不同。盡管對于那些了解這些系統的人來說,很容易對它們進行定制,但是很難學習這些系統,排錯也很困難。這是 GOF 提到的裝飾模式的缺點,你能體會嗎?他們所說的小對象我認為是指的具體裝飾角色。這是為一個對象動態添加功能所帶來的副作用。

    ?

    七、總結

    ?????? 終于寫完了,不知道說出了本意沒有。請指正!
    posted on 2006-08-29 18:57 Alex 閱讀(501) 評論(0)  編輯  收藏 所屬分類: design
    主站蜘蛛池模板: 一级毛片不卡免费看老司机| 午夜成年女人毛片免费观看| 暖暖免费中文在线日本| 两个人看www免费视频| 欧美男同gv免费网站观看| 亚洲美日韩Av中文字幕无码久久久妻妇| 亚洲成av人影院| 粉色视频成年免费人15次| 91av视频免费在线观看| 亚洲电影日韩精品 | 亚洲精品成人a在线观看| 亚洲AV电影天堂男人的天堂| 99xxoo视频在线永久免费观看| 免费久久精品国产片香蕉| 亚洲人成7777影视在线观看| 成全视频免费观看在线看| 免费二级毛片免费完整视频| 全部在线播放免费毛片| 亚洲一级特黄大片无码毛片 | 亚洲XX00视频| 免费毛片在线看不用播放器| 久久狠狠高潮亚洲精品| 三年在线观看免费观看完整版中文| 国产成人精品男人免费| 亚洲熟妇AV乱码在线观看| 全免费毛片在线播放| 亚洲精品电影在线| 免费女人高潮流视频在线观看 | 五月婷婷亚洲综合| 色偷偷尼玛图亚洲综合| 亚洲综合最新无码专区| 最近免费视频中文字幕大全| 亚洲精品国产摄像头| 精品国产免费观看| 久久免费99精品国产自在现线 | 亚洲av日韩av欧v在线天堂| 国产免费无码AV片在线观看不卡| 亚洲性猛交XXXX| 少妇性饥渴无码A区免费| 亚洲av日韩av综合| 在线观看免费大黄网站|