【設計模式攻略】結構型模式之Composite模式
阿新 • • 發佈:2019-02-04
概要
具備一系列既有獨立功能,又需要排列組合其中的幾種功能來達成一些複合的新功能時,可以採用組合模式。比如說,你設計了一個備份模組,有email備份,note備份,message備份,log備份等一系列備份功能,而你又會需要同時備份它們中間不定的幾種時,考慮用組合模式吧。它能組合物件處理,而又不增加額外的耦合,並保證介面一致,以及模組的易用性和擴充套件性。
目的
自由組合既有物件處理來實現複合物件,保證單一物件和複合物件具有統一的對外介面。
例項
Command模式應該都比較熟悉了,這裡結合Command模式來舉個例子。
有時我們會把行為(action)封裝為類,比如我們需要如下這些action,儲存action,備份action,傳送action,顯示action等,那麼考慮用Command模式來進行封裝,如下所示:
我們有需要實現幾種複合行為,Composite1是(儲存+備份)action,Composite2是(儲存+顯示)action,Composite3是(儲存+顯示+傳送)action,不要告訴我你會如下這樣去實現!為每種複合行為都設計一個類?
(省略Composite2, Composite3) 很容易看出,這不是一種好方法,擴充套件性太差,增加了類間的耦合度。如果又需要更多的不同的複合行為,難道再繼續追加類?太複雜,太煩了,模組維護者看到這種設計會瘋掉的。 那麼,讓我們看看如果用Composite模式是怎麼解決的。
設計一個CompositeAction類,具有跟其他Action統一的介面(Execute),CompositeAction包含一個基類CommandAction的list容器物件,通過AddAction和DeleteAction,可以由Client呼叫方自由追加和刪除複合物件中需要包含的Action,而Execute方法會執行list中push進來的所有Action。 應用 在檔案系統庫中,儲存檔案節點包含資料夾和檔案的組合,而一些UI庫中,複雜的UI也經常會由很多可定製的基本UI組成,當然相關應用還有很多,在這些庫中,Composite模式經常會被使用。另外Composite模式也經常跟Decorator模式結合起來使用,關於Decorator模式,在下一單元會有詳細的說明。
class CommandAction { public: virtual void Execute (); }; class SaveAction : public CommandAction { public: virtual void Execute (); }; class BackupAction : public CommandAction { public: virtual void Execute (); }; class SendAction : public CommandAction { public: virtual void Execute (); }; ......
我們有需要實現幾種複合行為,Composite1是(儲存+備份)action,Composite2是(儲存+顯示)action,Composite3是(儲存+顯示+傳送)action,不要告訴我你會如下這樣去實現!為每種複合行為都設計一個類?
class CommandAction { public: virtual void Execute (); }; class Composite1: public CommandAction { public: ...... virtual void Execute () { mSave->Execute(); mBackup->Execute(); } private: SaveAction* mSave; BackupAction * mBackup; };
(省略Composite2, Composite3) 很容易看出,這不是一種好方法,擴充套件性太差,增加了類間的耦合度。如果又需要更多的不同的複合行為,難道再繼續追加類?太複雜,太煩了,模組維護者看到這種設計會瘋掉的。 那麼,讓我們看看如果用Composite模式是怎麼解決的。
class CommandAction {
public:
virtual void Execute() = 0;
virtual void AddAction(CommandAction* action);
virtual void DeleteAction(CommandAction* action);
};
class CompositeAction : public CommandAction {
public:
......
virtual void Execute() {
list<CommandAction*>::iterator it;
for (it = mCompositor.begin(); it != mCompositor.end(); it++) {
if (*it != NULL) {
(*it)->Execute(pack);
}
}
}
virtual void AddAction(CommandAction* action) {
if (action != NULL) {
mCompositor.push_back(action);
}
}
virtual void DeleteAction(CommandAction* action) {
list<CommandAction*>::iterator it;
if (action != NULL) {
for (it = mCompositor.begin(); it != mCompositor.end(); it++) {
if (*it == action) {
mCompositor.erase(it);
break;
}
}
}
private:
list<CommandAction*> mCompositor;
};
設計一個CompositeAction類,具有跟其他Action統一的介面(Execute),CompositeAction包含一個基類CommandAction的list容器物件,通過AddAction和DeleteAction,可以由Client呼叫方自由追加和刪除複合物件中需要包含的Action,而Execute方法會執行list中push進來的所有Action。 應用 在檔案系統庫中,儲存檔案節點包含資料夾和檔案的組合,而一些UI庫中,複雜的UI也經常會由很多可定製的基本UI組成,當然相關應用還有很多,在這些庫中,Composite模式經常會被使用。另外Composite模式也經常跟Decorator模式結合起來使用,關於Decorator模式,在下一單元會有詳細的說明。