組合模式:將對象組合成樹形結構以表示「部分-整體」層次。使客戶端對單個對象和組合對象的使用具有一致性。屬於結構型模式。
operation()、add()、remove()、getChild()。operation(),add/remove/getChild 拋異常或空實現。add/remove/getChild,operation() 遞歸調用子構件。class Component {
public:
virtual ~Component() {}
virtual void operation() = 0;
virtual void add(Component* c) { throw runtime_error("Not supported"); }
virtual void remove(Component* c) { throw runtime_error("Not supported"); }
virtual Component* getChild(size_t idx) { return nullptr; }
};
class Leaf : public Component {
public:
void operation() override { cout << "Leaf\n"; }
};
class Composite : public Component {
vector children;
public:
~Composite() { for (auto c : children) delete c; }
void operation() override {
cout << "Composite (children: " << children.size() << ")\n";
for (auto c : children) c->operation();
}
void add(Component* c) override { children.push_back(c); }
void remove(Component* c) override {
auto it = find(children.begin(), children.end(), c);
if (it != children.end()) children.erase(it);
}
Component* getChild(size_t idx) override {
return (idx < children.size()) ? children[idx] : nullptr;
}
};
// 使用
int main() {
Component* root = new Composite();
root->add(new Composite());
root->add(new Leaf());
root->getChild(0)->add(new Leaf());
root->getChild(0)->add(new Leaf());
root->operation();
delete root;
}
| 風格 | Component 聲明 | 優點 | 缺點 |
|---|---|---|---|
| 透明式 | add/remove/getChild 在 Component 中聲明 | 客戶端統一調用,無需區分葉子/容器 | 葉子類被迫實現無意義方法(拋異常) |
| 安全式 | add/remove/getChild 只在 Composite 中聲明 | 類型安全,葉子不受污染 | 客戶端需轉型調用,破壞一致性 |
本文代碼採用透明式(GoF 推薦),利用異常/空實現處理葉子不支持的操作。
Component <|-- Leaf
Component <|-- Composite
Composite o-- Component (children)
Container 繼承 Component。Directory 和 File 實現共同接口。組合模式將遞歸數據結構映射為遞歸類結構。核心:Component 定義統一接口,Leaf 實現基本行為,Composite 遞歸委託子構件。透明式雖讓葉子背負無用方法,但換來客戶端代碼極致簡潔,是經典權衡。