Franky's LIFE

          Anything... ...

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            53 隨筆 :: 87 文章 :: 6 評論 :: 0 Trackbacks
          Composite 組 合模式主要是應(yīng)對這樣的問題:一類具有“容器特征”的對象——即他們在充當(dāng)對象的同時,又是其他對象的容器的情況。在編寫時我們常常會造成:客戶代碼過多 地依賴于對象容器復(fù)雜的內(nèi)部實現(xiàn),對象容器內(nèi)部實現(xiàn)結(jié)構(gòu)(而非抽象接口)的變化將引起客戶代碼的頻繁變化,帶來了代碼的維護性、擴展性的弊端。

          ?????? GoF 《設(shè)計模式》中說到:將對象組合成樹形結(jié)構(gòu)以表示“部分 - 整體”的層次結(jié)構(gòu)。 Composite 模式使得客戶對單個對象和組合對象的使用具有一致性。

          ?????? Composite 組合模式結(jié)構(gòu)如下:



          ??????
          說道這,我覺得有一個編程中常見的場景,就是對于樹的實現(xiàn),很符合這個模式。下面我就用這個例子作一下。

          ?????? 首先,我們先分析對于一棵樹所包含的部分,樹干、樹枝、樹葉,其中樹干可以看成一個樹枝(就是粗了點)。那么我們就應(yīng)該有兩種類實現(xiàn) Leaf (樹葉)和 Limb (樹枝)。對于葉子節(jié)點和枝節(jié)點的不同在于枝節(jié)點有子樹,而葉子節(jié)點沒有子樹。為了使單個對象和組合對象的使用具有一致性,我可以將葉子節(jié)點想象成沒有子樹的枝節(jié)點。這樣我就可以得到一個抽象類,代碼如下:

          ?????? public abstract class AbstractClass

          ??? {

          ??????? public string name;

          ??????? public ArrayList list;

          ??????? public abstract void Add(AbstractClass item);?????? // 增加一個子節(jié)點

          ??????? public abstract void Remove(AbstractClass item);??? // 去掉一個子節(jié)點

          ??????? public abstract string Print();???????????????????? // 打印當(dāng)前節(jié)點

          ??? }

          ?????? 然后,我在對葉子節(jié)點和枝節(jié)點作不同的實現(xiàn):

          ?????? 枝節(jié)點:

          ?????? public class Limb:AbstractClass

          ??? {

          ??????? public Limb()

          ??????? {

          ??????????? list = new ArrayList();

          ??????? }

          ?

          ??????? public override void Add(AbstractClass item)

          ??????? {

          ??????????? list.Add(item);

          ??????? }

          ?

          ??????? public override void Remove(AbstractClass item)

          ??????? {

          ??????????? if(list.Contains(item))

          ??????????????? list.Remove(item);

          ??????? }

          ??????? public override string Print()

          ??????? {

          ??????????? Console.Write(name + "\n");

          ??????????? if(list.Count != 0)

          ??????????? {

          ??????????????? for(int i = 0;i<list.Count;i++)

          ??????????????? {

          ??????????????????? Console.Write("(Parent is " + name + ")");

          ??????????????????? ((AbstractClass)list[i]).Print();

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

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

          ??????????? return name;

          ??????? }

          ?

          ??? }

          ??? 葉子節(jié)點:

          ??? public class Leaf:AbstractClass

          ??? {

          ??????? public Leaf()

          ??????? {

          ??????????? list = null;

          ??????? }

          ?

          ??????? public override void Add(AbstractClass item)

          ??????? {

          ?

          ??????? }

          ??????? public override void Remove(AbstractClass item)

          ??????? {

          ???????????

          ??????? }

          ??????? public override string Print()

          ??????? {

          ??????????? Console.Write(name + ",");

          ??????????? return this.name;

          ??????? }

          ??? }

          ??? 對于葉子節(jié)點來說,不需要子節(jié)點,當(dāng)然也就不需要添加和刪除子節(jié)點的方法。

          ??? 好,接下來,我們可以在客戶程序中組建一棵樹,來測試一下:

          ??????? static void Main(string[] args)

          ??????? {

          ??????????? AbstractClass Tree = new Limb();

          ??????????? GetTree(Tree);

          ??????????? PrintTree(Tree);

          ??????????? Console.Read();

          ??????? }

          ?

          ??? ??? public static void GetTree(AbstractClass Tree)

          ??????? {

          ??????????? Tree.name = "1";

          ??????????? AbstractClass leaf2 = new Leaf();

          ??????????? leaf2.name = "2";

          ??????????? Tree.Add(leaf2);

          ??????????? AbstractClass limb3 = new Limb();

          ??????????? limb3.name = "3";

          ??????????? Tree.Add(limb3);

          ??????????? AbstractClass leaf4 = new Leaf();

          ??????????? leaf4.name = "4";

          ??????????? limb3.Add(leaf4);

          ??????????? AbstractClass leaf5 = new Leaf();

          ??????????? leaf5.name = "5";

          ??????????? limb3.Add(leaf5);

          ??????? }

          ?

          ??????? public static void PrintTree(AbstractClass Tree)

          ??????? {

          ??????????? Tree.Print();

          ??????? }

          ??? 輸出結(jié)果如下:

          1

          (Parent is 1)2,(Parent is 1)3

          (Parent is 3)4,(Parent is 3)5,

          在組織這個樹時,的確能感覺到 GoF 《設(shè)計模式》中的那句話: 單個對象和組合對象的使用具有一致性。當(dāng)然也的確感覺到一點矛盾:對于葉子節(jié)點來說,不需要 ArrayList Add () Remove ()應(yīng)該不繼承才對,當(dāng)然如果在代碼執(zhí)行性能可以達到要求的情況下,簡化一下編碼實現(xiàn)復(fù)雜度也是挺好的一件事。

          最后在來說說 Composite 組合模式的幾個要點:

          ?????? 1 Composite 模式采用樹形結(jié)構(gòu)來實現(xiàn)普遍存在的對象容器,從而將“一對多”的關(guān)系轉(zhuǎn)化為“一對一”的關(guān)系,使得客戶代碼可以一致的處理對象和對象容器,無需關(guān)心處理的是單個對象,還是組合的對象容器。

          2 、將“客戶代碼與復(fù)雜的對象容器結(jié)構(gòu)”解耦是 Composite 模式的核心思想,解耦之后,客戶代碼將與純粹的對象接口——而非對象容器的復(fù)雜內(nèi)部實現(xiàn)結(jié)構(gòu)——發(fā)生依賴關(guān)系,從而更能“應(yīng)對變化”。

          3 Composite 模式中,是將“ Add Remove 的和對象容器相關(guān)的方法”定義在“表示抽象對象的 Component 類”中,還是將其定義在“表示對象容器的 Composite 類”中,是一個關(guān)乎“透明性”和“安全性”的兩難問題,需要仔細(xì)權(quán)衡結(jié)構(gòu),這又是必須付出的代價。

          4 Composite 模式在具體實現(xiàn)中,可以讓父對象中的字對象反向追溯:如果父對象有頻繁的遍歷需求,可使用緩存技巧來改善效率

          posted on 2007-03-19 20:55 Franky 閱讀(177) 評論(0)  編輯  收藏 所屬分類: IT知識
          主站蜘蛛池模板: 瓮安县| 霍林郭勒市| 颍上县| 布拖县| 谢通门县| 汉川市| 宝坻区| 普定县| 南丹县| 固安县| 平湖市| 新津县| 溆浦县| 思茅市| 大渡口区| 广州市| 鹿邑县| 钦州市| 平乐县| 永州市| 定安县| 新干县| 原平市| 怀宁县| 襄垣县| 镇雄县| 霞浦县| 关岭| 安仁县| 友谊县| 普洱| 林西县| 平顶山市| 昭通市| 泽普县| 嵊州市| 德阳市| 个旧市| 绥江县| 绵阳市| 桂林市|