回到問題的本質,為什麼新增甜品後迭代器就無法工作了?因為昨天是針對菜品實現的迭代器,而甜品是乙個子選單,並不支援菜品的某些操作(獲取**),也就是它們的操作不一致導致迭代器需要作出更多複雜的判斷才能完成昨天同樣的功能。那為什麼組合模式就可以解決這個問題呢?先來看看它的定義:
組合模式允許你將物件組合成樹形結構來表現「整體/部分」層次結構。組合能讓客戶以一致的方式處理個別物件及物件組合。還有什麼比電腦的資料夾更能直觀的說明這個模式的呢?下面我實現乙個簡單的listfiles功能。首先我們需要乙個公共的抽象類(可以是介面也可以是抽象類):
public
abstract
class
file
/** * 往資料夾新增檔案,返回false表示不支援新增或新增失敗
*/public
boolean
addfile
(file file)
public string getname()
public
double
getsize()
public
boolean
isfolder()
/** * 修改檔案內容,返回false表示不支援修改
*/public
boolean
edit()
/** * 顯示資料夾下所有的檔案,返回false表示不是資料夾不支援該操作
*/public
boolean
print()
}
資料夾本質上也是乙個檔案,所以我這裡抽象出乙個file抽象類,提供了新增檔案、修改檔案、是否是資料夾以及顯示資料夾下所有的檔案等操作,當然檔案和資料夾不可能都支援所有的操作,因此你可以將方法都預設丟擲乙個unsupportedoperationexception異常,不過我這裡是返回乙個預設的boolean值(想一想為什麼?)。接下來實現具體的檔案類:
public
class
imagefile
extends
file
}public
class
textfile
extends
file
@override
public
boolean
edit()
}
public
class
folder
extends
file
/** * 新增檔案到資料夾並計算總大小
*/@override
public
boolean
addfile
(file file)
@override
public
boolean
isfolder()
@override
public
boolean
print()
else
}return
true;}
}
資料夾系統則只需要實現isfolder和print方法,前者告訴呼叫者這是乙個資料夾,後者則顯示出其下所有的檔案,這裡需要注意的是如果你在處理不支援的操作時是丟擲的異常,那這裡就需要捕獲異常,這樣**不僅不優雅,還會影響效能(異常例項的構造是相當昂貴的,若非必要,盡量不要使用,感興趣的可以參考《深入理解jvm》一書)。最後測試一下:
public
static
void
main
(string[
] args)
客戶端只需要呼叫print方法就能顯示出所有的資料夾和檔案,無需知道具體的實現細節,所以對客戶而言組合(資料夾)和葉節點(檔案)是透明的(也就是組合和葉節點能夠統一處理),這樣看組合模式是不是很強大?
但是組合模式也是有缺點的,它違反了單一職責原則,它需要維護整個組合的層次結構,同時還要執行相關的操作,這就讓component有了多個改變的理由,不過以此換取對客戶的透明性還是很有必要的。
通過組合模式我們學到了如何對客戶保證透明性,使得客戶能夠非常便捷的使用我們提供的方法,也使**變得更加整潔優美。
同時我們也應該明白不能固執的遵守設計原則,有時打破比遵守能呈現出更好的設計。
《設計模式之禪》之組合模式
組合模式也叫合成模式,有時又叫做部分 整體模式,主要用來描述部分與整體的關係,其定義如下 將物件組合成的樹形結構以表示 部分 整體 的層次結構,使得使用者對單個物件和組合物件的使用具有一致性。1 component抽象構件角色 定義參加組合物件的共有方法和屬性,可以定義一些預設的行為或屬性 2 le...
《設計模式之禪》 組合模式 1
這是乙個常見的資料庫結構 比較典型的樹狀結構 常見的還有選單 一般的做法 ceo我們認為是根節點 developdep,developgroup,salesdep,fiancedep是樹枝節點 k,a,b則是樹葉節點 樹葉節點是最小的節點.不能延伸或者有分支 一般的做法是定義三個介面用來定義三個角色...
設計模式之禪
設計模式之禪 大話面向初學者 禪面向有了一定基礎後提公升能力的讀者 看大話,只是看故事,只是感性認識,對於很多初學者而又沒專案經驗 或 閱讀 編寫量 的人來說,比較適合用於入門 看禪 主要是有一定的專案經驗 或 閱讀 編寫量 基礎上,而又大致閱讀過23種設計模式中的20種以上基本概念後,再深化提公升...