🔄 回顧 Day 13:橋接模式小結
在 Day 13 中,我們學習了橋接模式(Bridge Pattern):
- 用于將“抽象”與“實現”分離,適用于雙維度變化場景(如圖形類型 × 渲染方式)。
- 它強調組合替代繼承,解決類爆炸問題,提升系統可擴展性。
今天我們進入一個構建層級結構的重要模式——組合模式(Composite Pattern)。
組合模式的目標是:讓你以一致的方式對待單個對象和對象集合(樹形結構)。
一、組合模式的核心動機
? 什么是組合模式?
組合模式用于構建樹狀結構的對象系統,例如:
- 文件夾包含文件和子文件夾
- UI 容器包含多個控件
- 公司組織結構:員工 ← 部門 ← 公司
核心哲學:
將對象組成樹形結構,客戶端可以“統一操作”葉子節點與中間節點。
二、UML 結構圖
+----------------+
| Component |<------------------------------+
+----------------+ |
| +operation() | |
+----------------+ |/\ |/ \ |
+-------------------+ +---------------------+ |
| Leaf | | Composite | |
+-------------------+ +---------------------+ |
| +operation() | | +add(Component*) | || +remove(Component*) | || +operation() | |+---------------------+ |
三、角色說明
角色 | 職責說明 |
---|---|
Component | 抽象類,統一接口 |
Leaf | 葉子節點,實現具體功能,不含子節點 |
Composite | 組合節點,內部維護子組件列表 |
四、C++ 實現:文件系統結構
? 抽象組件接口
class FileSystemNode {
public:virtual void display(int depth = 0) = 0;virtual ~FileSystemNode() = default;
};
? 葉子節點:文件
class File : public FileSystemNode {std::string name_;
public:File(const std::string& name) : name_(name) {}void display(int depth = 0) override {std::cout << std::string(depth, '-') << name_ << std::endl;}
};
? 組合節點:文件夾
class Directory : public FileSystemNode {std::string name_;std::vector<std::unique_ptr<FileSystemNode>> children_;public:Directory(const std::string& name) : name_(name) {}void add(std::unique_ptr<FileSystemNode> node) {children_.emplace_back(std::move(node));}void display(int depth = 0) override {std::cout << std::string(depth, '-') << name_ << "/" << std::endl;for (const auto& child : children_) {child->display(depth + 2);}}
};
? 使用示例
int main() {auto root = std::make_unique<Directory>("root");root->add(std::make_unique<File>("file1.txt"));auto subDir = std::make_unique<Directory>("subdir");subDir->add(std::make_unique<File>("file2.txt"));subDir->add(std::make_unique<File>("file3.txt"));root->add(std::move(subDir));root->display();return 0;
}
輸出:
root/
--file1.txt
--subdir/
----file2.txt
----file3.txt
五、組合模式適用場景
場景 | 對象樹結構說明 |
---|---|
操作系統文件系統 | 文件 + 文件夾,操作接口統一 |
圖形界面控件 | 窗口、容器、按鈕、文本框構成控件樹 |
公司組織架構 | CEO → 部門主管 → 員工 |
報表結構層級 | 表頭、表體、表尾、字段 |
HTML DOM 樹 | 節點 + 元素 + 屬性 |
六、優點與缺點總結
? 優點:
- 統一接口,客戶端無差別調用
- 樹結構天然適合層次建模
- 擴展方便,添加新節點只需實現 Component
? 缺點:
- 違背接口隔離原則:葉子節點和組合節點共用接口,部分函數空實現
- 調試復雜,結構越深越難定位問題
七、與裝飾器 / 責任鏈等模式對比
模式 | 核心區別 | 類似點 |
---|---|---|
Composite | 結構樹形,有聚合子對象 | Component 接口統一 |
Decorator | 功能增強,包裹單一對象 | 接口一致、動態組合 |
Chain | 責任鏈傳遞,節點決定是否繼續傳遞 | 多節點連接,共同參與處理 |
八、面試回答模板
“在我們的配置中心中,使用組合模式構建配置節點樹,既可以是葉子屬性(字段),也可以是組合節點(嵌套組)。所有節點都繼承自統一接口,使我們可以用遞歸統一地遍歷配置結構、序列化、驗證,代碼簡潔且擴展性好。”
? 建議突出樹形結構、遞歸遍歷、統一調用等優勢。
九、記憶口訣
“樹形結構走統一,組合調用不分離;葉子整體皆一類,層層嵌套遞歸易。”
十、明日預告:Day 15
享元模式(Flyweight Pattern):通過共享技術減少對象數量,提升內存利用效率。