C++设计模式之组合模式攻略
简介
组合模式(Composite Pattern)是一种结构型设计模式。组合模式可以将对象组合成树形结构,表示“部分-整体”的结构层次关系,让客户端统一对待单个对象和组合对象。
结构
组合模式将对象组织成树形结构,有以下三个角色:
Component(抽象构件)
抽象构件定义了叶子和容器构件的公共接口,并可以提供一些默认的行为或属性。
class Component {
public:
virtual ~Component() {}
virtual void operation() = 0;
};
Leaf(叶子构件)
叶子构件是组成对象的最基本单元,其没有子节点,实现了抽象构件中的操作。
class Leaf : public Component {
public:
virtual void operation() {
// 叶子构件的操作
}
};
Composite(容器构件)
容器构件包含一组子节点,其中部分或所有子节点是另一个容器构件,其实现了抽象构件中的操作,并且可以在内部管理子节点。
class Composite : public Component {
private:
vector<Component*> components;
public:
virtual void operation() {
for (auto c : components) {
c->operation();
}
}
void addComponent(Component* c) {
components.push_back(c);
}
void removeComponent(Component* c) {
// 移除指定子节点
}
};
示例1:菜单栏
假设我们正在开发一个图形界面程序,需要实现一个具备子菜单的菜单栏。用组合模式可以轻松实现该功能。
int main() {
Composite* menuBar = new Composite; // 菜单栏
Composite* fileMenu = new Composite; // 文件菜单
Composite* editMenu = new Composite; // 编辑菜单
Leaf* openItem = new Leaf; // 打开文件项
Leaf* saveItem = new Leaf; // 存储文件项
Leaf* copyItem = new Leaf; // 复制项
Leaf* pasteItem = new Leaf; // 粘贴项
fileMenu->addComponent(openItem);
fileMenu->addComponent(saveItem);
editMenu->addComponent(copyItem);
editMenu->addComponent(pasteItem);
menuBar->addComponent(fileMenu);
menuBar->addComponent(editMenu);
menuBar->operation(); // 显示菜单栏及其子菜单
return 0;
}
示例2:文件系统
下面是一个文件系统的例子。文件系统由一个根目录和多个文件和子目录组成。
class FileSystemNode {
public:
virtual ~FileSystemNode() {}
virtual int getNumOfFiles() = 0;
virtual int getSize() = 0;
virtual string getName() = 0;
virtual void addNode(FileSystemNode* node) = 0;
virtual void removeNode(FileSystemNode* node) = 0;
};
class File : public FileSystemNode {
public:
File(const string& name, int size) : name_(name), size_(size) {}
virtual int getNumOfFiles() { return 1; }
virtual int getSize() { return size_; }
virtual string getName() { return name_; }
virtual void addNode(FileSystemNode* node) {}
virtual void removeNode(FileSystemNode* node) {}
private:
string name_;
int size_;
};
class Directory : public FileSystemNode {
public:
Directory(const string& name) : name_(name), size_(0) {}
virtual ~Directory() {
for (auto n : nodes_) {
delete n;
}
}
virtual int getNumOfFiles() {
int count = 0;
for (auto n : nodes_) {
count += n->getNumOfFiles();
}
return count;
}
virtual int getSize() { return size_; }
virtual string getName() { return name_; }
virtual void addNode(FileSystemNode* node) {
nodes_.push_back(node);
size_ += node->getSize();
}
virtual void removeNode(FileSystemNode* node) {
auto it = find(nodes_.begin(), nodes_.end(), node);
if (it != nodes_.end()) {
nodes_.erase(it);
size_ -= node->getSize();
}
}
private:
string name_;
int size_;
vector<FileSystemNode*> nodes_;
};
int main() {
Directory* root = new Directory("R:");
Directory* cDrive = new Directory("C:");
Directory* dDrive = new Directory("D:");
File* msPaint = new File("mspaint.exe", 112);
File* myFile = new File("myFile.txt", 10);
Directory* music = new Directory("Music");
root->addNode(cDrive);
root->addNode(dDrive);
cDrive->addNode(msPaint);
cDrive->addNode(myFile);
dDrive->addNode(music);
music->addNode(new File("song1.mp3", 8));
music->addNode(new File("song2.mp3", 9));
music->addNode(new Directory("Pop"));
music->addNode(new Directory("Rock"));
cout << "Num of files: " << root->getNumOfFiles() << endl;
cout << "Total size: " << root->getSize() << endl;
return 0;
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++设计模式之组合模式 - Python技术站