C++ 组合模式

什么是组合模式?
  • 组合模式是一种结构型设计模式,通过组合多个相同或不同的对象最终构成的树形结构。
  • 具有整体-部分关系的层次结构,无论是对叶子节点还是对于树节点的调用接口具有一致性。
  • 组合模式又称为部分-整体模式
如何理解组合模式?

这里以电脑的“文件夹”和“文件”为例:
一个文件夹中可以包含零到多个文件夹和文件,而每个子文件夹又可以包含孙子文件夹和文件,以此类推。
那如何知道当前文件夹的大小呢?这时候我们可以把文件夹和文件的大小抽象成一个接口。文件夹作为树(Composite)节点,文件作为叶子(leaf)节点

  • 文件夹的大小=所有当前子文件夹的大小+所有当前子文件大小
  • 文件大小=当前文件大小

看到下面的图,有没有觉得这好像和Qt的元对象树很像呢!!!
在这里插入图片描述

代码描述
  • 首选是需要统一的抽象接口
class I_Component {
public:
	virtual ~I_Component() {}
	virtual void Add(std::shared_ptr<I_Component> cmpt){};
	virtual void Remove(std::shared_ptr<I_Component> cmpt){};
	virtual void Operation() = 0;
};
  • 定义树节点,输节点具有遍历当其任意子节点的功能
class CompositeEntity : public I_Component {
public:
	CompositeEntity(const string& s) : name(s) {}
	virtual void Add(std::shared_ptr<I_Component> element) override {
		elements.push_back(element);
	}
	virtual void Remove(std::shared_ptr<I_Component> element) override {
		elements.remove(element);
	}
	virtual void Operation()
	{
		cout << name << endl;
		cout << "this is Composite has children size=" << elements.size() << endl;
		for (auto& leaf : elements) {
			leaf->Operation();
		}
	}

private:
	string                             name;
	list<std::shared_ptr<I_Component>> elements;
};
  • 定义叶子点
class LeafEntity : public I_Component {
public:
	LeafEntity(string s) : name(s) {}
	virtual void Operation(){
		cout << "this is leaf:" << name<< endl;
	}

private:
	string name;
};

这时候当我们想获取某一个节点下的详细信息,只需要调用抽象接口Operation方法即可

static void ShowComponent(std::shared_ptr<I_Component> c)
{
	c->Operation();
	cout << "\r" << endl;
}

int main()
{
	std::shared_ptr<I_Component> pRoot = std::make_shared<CompositeEntity>("pRoot");

	std::shared_ptr<I_Component> pPart1 = std::make_shared<CompositeEntity>("pPart1");
	pPart1->Add(std::make_shared<LeafEntity>("Leaf1-1"));
	pPart1->Add(std::make_shared<LeafEntity>("Leaf1-2"));

	std::shared_ptr<I_Component> pPart2 = std::make_shared<CompositeEntity>("pPart2");
	std::shared_ptr<I_Component> pPart2_1 = std::make_shared<CompositeEntity>("pPart2_1");
	pPart2->Add(std::make_shared<LeafEntity>("Leaf2-1"));
	pPart2->Add(std::make_shared<LeafEntity>("Leaf2-2"));
	pPart2->Add(pPart2_1);

	std::shared_ptr<I_Component> leaf_999 = std::make_shared<LeafEntity>("leaf_999");
	pPart2_1->Add(leaf_999);
	pRoot->Add(pPart1);
	pRoot->Add(pPart2);

	//获取根节点下的数据
	ShowComponent(pRoot); 
	//获取某一个节点下的数据
	ShowComponent(pPart2_1);

	return 0;
}
组合模式的思考

对于系统对象层次具备整体和部分的特征,并且可以构造出呈树形结构,这属于组合模式的适用场景,实际场景如公司的组织架构,电脑的目录结构。
通过组合模式可以最终把不同的叶子节点,抽象成相同的节点,达成了忽略整体-部分差异,最终给用户的是统一的抽象接口。

优势:

  • 可以结合C++的多态和递归设计出复杂的树形结构,但接口单一;
  • 符合开闭原则,当需要增加新的节点或树时,无需修改原有代码,并且可以成为现有树节点的一部分;

劣势:

  • 如果本质上叶子节点差异巨大时,很难抽象,只能通过适配器or桥接的形式给叶子节点提供适配接口,代码会变得难以理解;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值