<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,快速開(kāi)發(fā)
    最近關(guān)心的內(nèi)容:SSH,seam,flex,敏捷,TDD
    本站的官方站點(diǎn)是:顛覆軟件

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      220 隨筆 :: 9 文章 :: 421 評(píng)論 :: 0 Trackbacks

    一、 引子

    在大學(xué)的數(shù)據(jù)結(jié)構(gòu)這門(mén)課上,樹(shù)是最重要的章節(jié)之一。還記得樹(shù)是怎么定義的嗎?樹(shù) (Tree) n(n≥0) 個(gè)結(jié)點(diǎn)的有限集 T T 為空時(shí)稱(chēng)為空樹(shù),否則它滿(mǎn)足如下兩個(gè)條件:

    (1)??? 有且僅有一個(gè)特定的稱(chēng)為根 (Root) 的結(jié)點(diǎn);

    (2)?? 其余的結(jié)點(diǎn)可分為 m(m≥0) 個(gè)互不相交的子集 Tl T2 Tm ,其中每個(gè)子集本身又是一棵樹(shù),并稱(chēng)其為根的子樹(shù) (SubTree)

    上面給出的遞歸定義刻畫(huà)了樹(shù)的固有特性:一棵非空樹(shù)是由若干棵子樹(shù)構(gòu)成的,而子樹(shù)又可由若干棵更小的子樹(shù)構(gòu)成。而這里的子樹(shù)可以是葉子也可以是分支。

    今天要學(xué)習(xí)的組合模式就是和樹(shù)型結(jié)構(gòu)以及遞歸有關(guān)系。

    ?

    二、 定義與結(jié)構(gòu)

    組合 (Composite) 模式的其它翻譯名稱(chēng)也很多,比如合成模式、樹(shù)模式等等。在《設(shè)計(jì)模式》一書(shū)中給出的定義是:將對(duì)象以樹(shù)形結(jié)構(gòu)組織起來(lái),以達(dá)成 部分-整體 的層次結(jié)構(gòu),使得客戶(hù)端對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。

    從定義中可以得到使用組合模式的環(huán)境為: 在設(shè)計(jì)中想表示對(duì)象的 部分 整體 層次結(jié)構(gòu);希望用戶(hù)忽略組合對(duì)象與單個(gè)對(duì)象的不同,統(tǒng)一地使用組合結(jié)構(gòu)中的所有對(duì)象。

    看下組合模式的組成。

    1)???????? 抽象構(gòu)件角色 Component :它為組合中的對(duì)象聲明接口,也可以為共有接口實(shí)現(xiàn)缺省行為。

    2)?????? 樹(shù)葉構(gòu)件角色 Leaf :在組合中表示葉節(jié)點(diǎn)對(duì)象 —— 沒(méi)有子節(jié)點(diǎn),實(shí)現(xiàn)抽象構(gòu)件角色聲明的接口。

    3)?????? 樹(shù)枝構(gòu)件角色 Composite :在組合中表示分支節(jié)點(diǎn)對(duì)象 —— 有子節(jié)點(diǎn),實(shí)現(xiàn)抽象構(gòu)件角色聲明的接口;存儲(chǔ)子部件。

    下圖為組合模式的類(lèi)圖表示。

    ?

    如圖所示:一個(gè) Composite 實(shí)例可以像一個(gè)簡(jiǎn)單的 Leaf 實(shí)例一樣,可以把它傳遞給任何使用 Component 的方法或者對(duì)象,并且它表現(xiàn)的就像是一個(gè) Leaf 一樣。

    可以看出來(lái),使用組合模式使得這個(gè)設(shè)計(jì)結(jié)構(gòu)非常靈活,在下面的例子中會(huì)得到進(jìn)一步的印證。

    ??????

    三、 安全性與透明性

    組合模式中必須提供對(duì)子對(duì)象的管理方法,不然無(wú)法完成對(duì)子對(duì)象的添加刪除等等操作,也就失去了靈活性和擴(kuò)展性。但是管理方法是在 Component 中就聲明還是在 Composite 中聲明呢?

    一種方式是在 Component 里面聲明所有的用來(lái)管理子類(lèi)對(duì)象的方法,以達(dá)到 Component 接口的最大化(如下圖所示)。目的就是為了使客戶(hù)看來(lái)在接口層次上樹(shù)葉和分支沒(méi)有區(qū)別 —— 透明性。但樹(shù)葉是不存在子類(lèi)的,因此 Component 聲明的一些方法對(duì)于樹(shù)葉來(lái)說(shuō)是不適用的。這樣也就帶來(lái)了一些安全性問(wèn)題。

    ?

    另一種方式就是只在 Composite 里面聲明所有的用來(lái)管理子類(lèi)對(duì)象的方法(如下圖所示)。這樣就避免了上一種方式的安全性問(wèn)題,但是由于葉子和分支有不同的接口,所以又失去了透明性。

    ????


    ????《設(shè)計(jì)模式》一書(shū)認(rèn)為:在這一模式中,相對(duì)于安全性,我們比較強(qiáng)調(diào)透明性。對(duì)于第一種方式中葉子節(jié)點(diǎn)內(nèi)不需要的方法可以使用空處理或者異常報(bào)告的方式來(lái)解決。

    ?

    四、 舉例

    這里以 JUnit 中的組合模式的應(yīng)用為例(JUnit門(mén))。

    JUnit 是一個(gè)單元測(cè)試框架,按照此框架下的規(guī)范來(lái)編寫(xiě)測(cè)試代碼,就可以使單元測(cè)試自動(dòng)化。為了達(dá)到“自動(dòng)化”的目的, JUnit 中定義了兩個(gè)概念: TestCase TestSuite TestCase 是對(duì)一個(gè)類(lèi)或者 jsp 等等編寫(xiě)的測(cè)試類(lèi);而 TestSuite 是一個(gè)不同 TestCase 的集合,當(dāng)然這個(gè)集合里面也可以包含 TestSuite 元素,這樣運(yùn)行一個(gè) TestSuite 會(huì)將其包含的 TestCase 全部運(yùn)行。

    然而在真實(shí)運(yùn)行測(cè)試程序的時(shí)候,是不需要關(guān)心這個(gè)類(lèi)是 TestCase 還是 TestSuite ,我們只關(guān)心測(cè)試運(yùn)行結(jié)果如何。這就是為什么 JUnit 使用組合模式的原因。

    JUnit 為了采用組合模式將 TestCase TestSuite 統(tǒng)一起來(lái),創(chuàng)建了一個(gè) Test 接口來(lái)扮演抽象構(gòu)件角色,這樣原來(lái)的 TestCase 扮演組合模式中樹(shù)葉構(gòu)件角色,而 TestSuite 扮演組合模式中的樹(shù)枝構(gòu)件角色。下面將這三個(gè)類(lèi)的有關(guān)代碼分析如下:

    ?

    //Test 接口 —— 抽象構(gòu)件角色

    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);

    }

    ?

    //TestSuite 類(lèi)的部分有關(guān)源碼 ——Composite 角色,它實(shí)現(xiàn)了接口 Test

    public class TestSuite implements Test {

    // 用了較老的 Vector 來(lái)保存添加的 test

    ?????? private Vector fTests= new Vector(10);

    ?????? private String fName;

    ?????? ……?

    /**

    ?????? ?* Adds a test to the suite.

    ?????? ?*/

    ?????? public void addTest(Test test) {??????????

    // 注意這里的參數(shù)是 Test 類(lèi)型的。這就意味著 TestCase TestSuite 以及以后實(shí)現(xiàn) Test 接口的任何類(lèi)都可以被添加進(jìn)來(lái)

    ????????????? fTests.addElement(test);

    ?????? }

    ?????? ……

    ?????? /**

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

    ?????? ?*/

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

    ????????????? int count= 0;

    ????????????? for (Enumeration e= tests(); e.hasMoreElements(); ) {

    ???????????????????? Test test= (Test)e.nextElement();

    ???????????????????? count= count + test.countTestCases();

    ????????????? }

    ????????????? return count;

    ?????? }

    ?????? /**

    ?????? ?* Runs the tests and collects their result in a TestResult.

    ?????? ?*/

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

    ????????????? for (Enumeration e= tests(); e.hasMoreElements(); ) {

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

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

    ???????????????????? Test test= (Test)e.nextElement();
    ?????????????????????????? //關(guān)鍵在這個(gè)方法上面

    ???????????????????? runTest(test, result);

    ????????????? }

    ?????? }
    ????????????//這個(gè)方法里面就是遞歸的調(diào)用了,至于你的Test到底是什么類(lèi)型的只有在運(yùn)行的時(shí)候得知
    ????????????public void runTest(Test test, TestResult result) {
    ?????????????????? test.run(result);
    ????????????}

    ……

    }

    ?

    //TestCase 的部分有關(guān)源碼 ——Leaf 角色,你編寫(xiě)的測(cè)試類(lèi)就是繼承自它

    public abstract class TestCase extends Assert implements Test {

    ?????? ……

    ?????? /**

    ?????? ?* Counts the number of test cases executed by run(TestResult result).

    ?????? ?*/

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

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

    ?????? }

    /**

    ?????? ?* Runs the test case and collects the results in TestResult.

    ?????? ?*/

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

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

    ?????? }

    ……

    }

    ?????? 可以看出這是一個(gè)偏重安全性的組合模式。因此在使用TestCase和TestSuite時(shí),不能使用Test來(lái)代替。

    ?

    五、 優(yōu)缺點(diǎn)

    從上面的舉例中可以看到,組合模式有以下優(yōu)點(diǎn):

    1)???????? 使客戶(hù)端調(diào)用簡(jiǎn)單,客戶(hù)端可以一致的使用組合結(jié)構(gòu)或其中單個(gè)對(duì)象,用戶(hù)就不必關(guān)心自己處理的是單個(gè)對(duì)象還是整個(gè)組合結(jié)構(gòu),這就簡(jiǎn)化了客戶(hù)端代碼。

    2)?????? 更容易在組合體內(nèi)加入對(duì)象部件 . 客戶(hù)端不必因?yàn)榧尤肓诵碌膶?duì)象部件而更改代碼。這一點(diǎn)符合開(kāi)閉原則的要求,對(duì)系統(tǒng)的二次開(kāi)發(fā)和功能擴(kuò)展很有利!

    當(dāng)然組合模式也少不了缺點(diǎn):組合模式不容易限制組合中的構(gòu)件。

    ?

    六、 總結(jié)

    組合模式是一個(gè)應(yīng)用非常廣泛的設(shè)計(jì)模式,在前面已經(jīng)介紹過(guò)的解釋器模式、享元模式中都是用到了組合模式。它本身比較簡(jiǎn)單但是很有內(nèi)涵,掌握了它對(duì)你的開(kāi)發(fā)設(shè)計(jì)有很大的幫助。

    這里寫(xiě)下了我學(xué)習(xí)組合模式的總結(jié),希望能給你帶來(lái)幫助,也希望您能給與指正。
    posted on 2006-08-29 21:44 Alex 閱讀(460) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): design
    主站蜘蛛池模板: 宅男666在线永久免费观看| 999国内精品永久免费视频| 伊人久久免费视频| 日韩视频在线精品视频免费观看| 成全影视免费观看大全二| 免费观看亚洲人成网站| 亚洲日韩激情无码一区| 亚洲欧洲日产v特级毛片| 亚洲狠狠婷婷综合久久蜜芽| 日韩精品无码免费视频| 中文字幕乱码一区二区免费| 色老头永久免费网站| 日本免费一区尤物| 国产亚洲精品一品区99热| 亚洲国产超清无码专区| 鲁啊鲁在线视频免费播放| 18禁在线无遮挡免费观看网站| 久草在视频免费福利| 亚洲国产日韩成人综合天堂| 亚洲国产成人久久精品动漫| 中国china体内裑精亚洲日本| 亚洲阿v天堂在线2017免费| 中国xxxxx高清免费看视频| 国产成人在线免费观看| 国产成人亚洲综合色影视| 亚洲色大成WWW亚洲女子| 中国性猛交xxxxx免费看| 最近2019中文免费字幕| 亚洲精品一品区二品区三品区| 亚洲人成www在线播放| 久久久受www免费人成| 国产免费av片在线看| 亚洲精品乱码久久久久久中文字幕| 激情内射亚洲一区二区三区爱妻| 一级成人a免费视频| 无码中文字幕av免费放| 亚洲午夜久久久久久久久电影网| 亚洲熟伦熟女专区hd高清| 暖暖免费在线中文日本| 免费又黄又爽又猛的毛片| 亚洲免费电影网站|