定義
將對象組合成樹形結構以表示部分-整體’的層次結構。Composite使得用戶對單個對象和組合對象的使用具有一致性(穩定)。
應用場景
- 在軟件在某些情況下,客戶代碼過多地依賴于對象容器復雜的內部實現結構,對象容器內部實現結構(而非抽象接口)的變化將引起客戶代碼的頻繁變化,帶來了代碼的維護性、擴展性等弊端。
- 如何將“客戶代碼與復雜的對象容器結構”解耦?讓對象容器自己來實現自身的復雜結構,從而使得客戶代碼就像處理簡單對象-樣來處理復雜的對象容器?
結構
代碼示例
//Composite.h
/****************************************************/
#ifndef COMPOSITE_H
#define COMPOSITE_H
#include <iostream>
#include <list>using namespace std;// 抽象類-節點
class Node
{
public:// 構造函數explicit Node(string name) :m_name(name) {};// 析構函數virtual ~Node() {};// 添加virtual void add(Node *node) {};// 刪除virtual void remove(Node *node) {};// 顯示virtual void show(int space) {for (int i = 0; i < space; i++) {cout << " ";}cout << m_name << endl;}protected:string m_name; // 名字
};// 具體類-Word文件
class WordFile :public Node
{
public:// 構造函數explicit WordFile(string name) :Node(name) {};// 析構函數virtual ~WordFile() {};};// 具體類-文件夾
class Folder :public Node
{
public:// 構造函數explicit Folder(string name) :Node(name) {};// 析構函數virtual ~Folder() {nodeList.clear();}// 添加virtual void add(Node *node) {nodeList.emplace_back(node);}// 刪除virtual void remove(Node *node) {nodeList.remove(node);}// 顯示virtual void show(int space) {Node::show(space);space++;for (auto node : nodeList) {node->show(space);}}private:list<Node*> nodeList; // 節點列表
};#endif
//test.cpp
/****************************************************/
#include "Composite.h"int main()
{Node *f0 = new Folder("我的文件夾");// 文件夾1中放入Word2和Word3,并將文件夾1放入我的文件夾Node *f1 = new Folder("文件夾1");Node *w2 = new WordFile("Word2");Node *w3 = new WordFile("Word3");f1->add(w2);f1->add(w3);f0->add(f1);// 將Word1放入我的文件夾Node *w1 = new WordFile("Word1");f0->add(w1);// 顯示我的文件夾中的內容f0->show(0);// 刪除文件夾1中的Word2文件,再次顯示我的文件夾中的內容f1->remove(w2);f0->show(0);// 刪除指針并置空delete f0, f1, w1, w2, w3;f0 = nullptr;f1 = nullptr;w1 = nullptr;w2 = nullptr;w3 = nullptr;return 0;
}
運行結果
要點總結
- Composite模式采用樹形結構來實現普遍存在的對象容器,從而將“一對多”的關系轉化為“一對一”的關系,使得客戶代碼可以一致地(復用)處理對象和對象容器,無需關心處理的是單個的對象,還是組合的對象容器。
- 將“客戶代碼與復雜的對象容器結構”解耦是Composite的核心思想,解耦之后,客戶代碼將與純粹的抽象接口一而非 對象容器的內部實現結構一發生依賴, 從而更能“應對變化”。
- Composite模式在具體實現中,可以讓父對象中的子對象反向追溯;如果父對象有頻繁的遍歷需求,可使用緩存技巧來改善效率。