組合模式是一種結構型設計模式,它允許將物件組合成樹形結構,以表示 "部分/整體" 的階層結構。用戶端可以用一致的方式來處理個別物件與物件組合
深入淺出設計模式 2nd (p.360)
主要區別在於 Interface 的設計: 是否所有的操作都對單一和複合對象都公開
在許多軟體應用,特別是圖形程式設計 (GUI) 應用中,組合模式主要用於管理與操作複雜的控件樹 (Widget Tree)。這種模式允許單一物件 (如單一按鈕) 和複合物件(如整個面板或窗口)能夠通過相同的介面進行操作,例如:
// Component
// 這是所有主菜單和副菜單將繼承的基礎類別
class MenuComponent {
public:
virtual void add(MenuComponent* menuComponent) {}
virtual void remove(MenuComponent* menuComponent) {}
virtual void print() {
std::cout << "General Menu Component" << std::endl;
}
};
// Leaf
// 這個類別表示一個單一菜單項目
class MenuItem : public MenuComponent {
private:
std::string name;
public:
MenuItem(const std::string& name) : name(name) {}
void print() override {
std::cout << "Menu Item: " << name << std::endl;
}
};
// Composite
// 這個類別包含多個 MenuComponent,這些可能是 MenuItem 或者是其他 Menu
class Menu : public MenuComponent {
private:
std::vector<MenuComponent*> menuComponents;
std::string name;
public:
Menu(const std::string& name) : name(name) {}
void add(MenuComponent* menuComponent) override {
menuComponents.push_back(menuComponent);
}
void remove(MenuComponent* menuComponent) override {
// Remove the menuComponent from menuComponents vector
}
void print() override {
std::cout << "Menu: " << name << std::endl;
for(auto& menuComponent : menuComponents) {
menuComponent->print();
}
}
};
// Client 端使用範例
int main() {
MenuComponent* mainMenu = new Menu("Main Menu");
MenuComponent* subMenu1 = new Menu("Sub Menu 1");
MenuComponent* subMenu2 = new Menu("Sub Menu 2");
MenuComponent* item1 = new MenuItem("Item 1");
MenuComponent* item2 = new MenuItem("Item 2");
mainMenu->add(subMenu1);
mainMenu->add(subMenu2);
subMenu1->add(item1);
subMenu2->add(item2);
mainMenu->print();
}
Output:
Menu: Main Menu
Menu: Sub Menu 1
Menu Item: Item 1
Menu: Sub Menu 2
Menu Item: Item 2