c++ 设计模式23讲之组合模式

组合模式

定义:

组合多个对象形成树形结构,实现部分-整体的层次关系

优点:

(1)很清楚的定义树形层次,结点和叶结点进行分割,便于扩展

(2)很灵活的递归组合

缺点:

(1)扩展的对象需要满足抽象接口的约束,相互间具有依赖关系

(2)组合深度很大时创建会很麻烦,也会创建很多的子对象

(3)类型转换时避免截断

使用范围:

满足树形结构,且子结点也可做为下一个组合的根节点(类似于容器);

案例:文件树、json解析

结构:

实现一个文件树的增删,包括文件和文件夹2中类型。

文件相当于叶结点;文件夹相当于子结点,子结点可以增加子结点和叶节点

实现:

namespace structural_pattern
{
	class composite_pattern
	{
	public:
		virtual void get_status() = 0;
		virtual void add_composite(composite_pattern* comp) {};
		virtual void remove_composite(composite_pattern* comp) {};
	public:
		short file_type;
		unsigned long file_id;
	};

	class file_composite_pattern : public composite_pattern
	{
	public:
		file_composite_pattern(short file_type, unsigned long file_id)
		{
			this->file_id = file_id;
			this->file_type = file_type;
		}
		void get_status() override
		{
			std::cout << "type[" << file_type <<"] id["<< file_id<<"]"<<std::endl;
		}
	};
	class folder_composite_pattern : public composite_pattern
	{
	public:
		folder_composite_pattern(short file_type, unsigned long file_id)
		{
			this->file_id = file_id;
			this->file_type = file_type;
		}
	
		void get_status() override
		{
			std::cout << "type[" << file_type << "] id[" << file_id << "]" << std::endl;
			for each (auto var in list_comp)
			{
#define FILE_NUM 10000
				for (auto i = var.get()->file_id / FILE_NUM;i; --i)
				{
					std::cout << "----";
				}
				var.get()->get_status();
			}
		}
		void add_composite(composite_pattern* comp)
		{
			list_comp.push_back(std::shared_ptr<composite_pattern>(comp));
			std::cout << "add " << "type[" << comp->file_type << "] id[" << comp->file_id << "]" << std::endl;
		}
		void remove_composite(composite_pattern* comp)
		{
			for (auto itr = list_comp.begin(); itr != list_comp.end(); ++itr)
			{
				if (itr->get()->file_id == comp->file_id && itr->get()->file_type == comp->file_type)
				{
					list_comp.erase(itr);
					std::cout<<"earse "<<  "type[" << comp->file_type << "] id[" << comp->file_id << "]" << std::endl;
				}
			}
		}
	private:
		std::vector<std::shared_ptr<composite_pattern>>list_comp{};
	};
}

测试:

基于GoogleTest 的单元测试框架;框架可参考如下网址:

https://www.cnblogs.com/jycboy/p/gtest_catalog.html

 

using namespace structural_pattern;
TEST(test_composite_pattern_add_composite, success_add_show)
{
	composite_pattern* c00 = new folder_composite_pattern(2, 00000);
	composite_pattern* c11 = new file_composite_pattern(1, 10001);
	composite_pattern* c12 = new folder_composite_pattern(2, 10002);
	composite_pattern* c21 = new file_composite_pattern(1, 20001);
	composite_pattern* c22 = new folder_composite_pattern(2, 20002);
	composite_pattern* c31 = new file_composite_pattern(1, 30001);
	composite_pattern* c13 = new file_composite_pattern(1, 10003);

	c22->add_composite(c31);
	c12->add_composite(c21);
	c12->add_composite(c22);
	c00->add_composite(c11);
	c00->add_composite(c12);
	c00->add_composite(c13);

	c00->get_status();
}

总结

(1)满足部分-整体层次关系才能使用这种设计模式

(2)考虑树的深度和广度,避免在内存创建过多的子对象

(3)增加新的构件类型需要考虑与结点的依赖关系

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值