設計模式系列漫談之八 復合模式

2022-02-28 07:47:42 字數 3190 閱讀 5860

故事

10月20日, 我們公司一行幾人參加紹興客戶的專案招標。出乎意料的是,就在當天,這家單位同時舉行三個專案的招標(真牛!),所以十幾家單位都在等候。我們上午8:30就到了現場,而我們投標的專案去排在下午進行。傻坐了一會,我們提議到魯迅故居去看看。其實幾次去紹興出差都匆匆忙忙的,今天終於如願以償。

近來確實鍛鍊太少,幾個小時下來,我的腳又酸又痛,已經累得走不動了。不過,其中兩幅圖給我深刻的印象。一幅是三維立體效果的紹興古城圖,講述著許多動人的故事;另一幅是周氏家族圖,象一棵參天大樹一樣,枝枝蔓蔓。可以看出,魯迅家族是浙江紹興會稽縣的乙個大家族。魯迅,原名周樹人,他還有兩個兄弟(周建人和周作人),他的父親叫周伯宜,他有個兒子叫周海嬰······,不說不了,再說就快暈了。

我在想乙個可笑的問題,在整個周氏家族裡,誰最能生兒子啊? 當然,我們沒有這麼多時間從頭至尾數一遍。那麼,就讓我們用程式來解決吧。

復合模式(composite)的解決方案

復合模式又叫部分-整體模式(part-whole)。將物件組織成樹型結構(周氏家族圖),可以用來描述整體與部分的關係,使客戶端將單純元素與復合元素同等看待,以此遍歷樹結構所有元素(所有周氏人)。復合模式需要定義三個物件:

抽象介面(ielement):這是乙個抽象類/介面,它給所有物件定義介面,提供操作行為,如statsons方法統計有多少個兒子。 

組合(composite)物件:代表包含子元素的組合。 

元素(element)物件:代表子元素物件。乙個子元素沒有下級子物件。

抽象介面如下:

namespace

lufamily

void

add(ielement t);

void

remove(ielement t);

void

statsons();}}

組合物件如下:

namespace

lufamily

set}

public

void

add(ielement t)

void

remove(ielement t)

void

statsons()}}

元素物件如下:

namespace

lufamily

set}

public

void

add(ielement t)

void

remove(ielement t)

void

statsons()}}

客戶端呼叫如下:

composite root

=new

composite();

root.name="

周伯宜"

;element e1

=new

element();

e1.name="

周建人"

;root.add(e1);

element e2

=new

element();

e2.name="

周作人"

;root.add(e1);

composite c1

=new

composite();

c1.name="

周樹人"

;root.add(c1);

element e3

=new

element();

e3.name="

周海嬰"

;c1.add(e3);

root.statsons();

也許您會問,既然元素物件(element)沒有下級子物件,為什麼還要實現add和remove方法呢?其實主要是為了實現客戶端對元素物件與組合物件統一對待,而不必區分哪個是元素物件,哪個是組合物件,這是復合模式兩種形式其中之一,即透明復合模式。採用這種方式的缺點是不夠安全,因為在實際應用中,元素物件與組合物件存在著本質區別。

復合模式的另一種形式自然是安全復合模式。採用安全復合模式就是把元素物件與組合物件的在本質上區分開來。即元素物件不需要提供add和remove等元素集合的管理方法。讓我們來看看安全復合模式的實現方法。

抽象介面如下:

namespace

lufamily

void

statsons();}}

組合物件如下:

namespace

lufamily

set}

public

void

add(ielement t)

void

remove(ielement t)

void

statsons()}}

元素物件如下:

namespace

lufamily

set}

void

statsons()}}

客戶端呼叫如下:

composite root

=new

composite();

root.name="

周伯宜"

;element e1

=new

element();

e1.name="

周建人";if

(root 

iscomposite)

root.add(e1);

element e2

=new

element();

e2.name="

周作人";if

(root 

iscomposite)

root.add(e1);

composite c1

=new

composite();

c1.name="

周樹人";if

(root 

iscomposite)

root.add(c1);

element ce1

=new

element();

ce1.name="

周海嬰";if

(c1 

iscomposite)

c1.add(ce1);

root.statsons();

為了安全起見,執行add方法的時候,最好判斷是否為組合物件。

設計模式系列漫談之七 命令模式

小雪的故事暫停,欲知後事如何,請等下回再編!現在改編另乙個故事。故事 小時候,我夢想自己成為一名真正的軍人,對軍營生活充滿著嚮往.軍人的豪氣,軍人的英姿總給人無限遐想。閒暇之餘,我喜歡看看軍事題材的電視劇集,包括 和平年代 歷史的天空 沙場點兵 中國近衛軍 垂直打擊 石破天驚 鐵色高原 今年一部電視...

設計模式系列之八外觀模式

外觀模式 提供了乙個統一的介面,用來訪問子系統的一群介面。外觀定義了乙個高層介面,讓子系統更容易使用。下面通過乙個圖來說明外觀模式的使用,此圖來自於 head first設計模式 一書。從上圖中可以看到,通過乙個統一的facade來呼叫複雜的子系統的類。按我的理解,外觀模式實際上就是抽取一些公共的業...

設計模式系列漫談之十二 職責鏈模式

從牙膏廣告說起 在午茶小憩間,以 成語接龍 形式,通過帥哥美女之口巧妙地把牙齒常見的症狀表達出來,從而突出雲南白藥牙膏的獨特功效。這一極其創意的廣告為雲南白藥贏得了巨大的市場,也使其產品為廣大消費者所熟悉,創造了家喻戶曉的品牌效應。成語接龍是一種人們喜聞樂見的遊戲。就遊戲規則來講非常簡單,即用前乙個...