• 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;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 定义树节点,输节点具有遍历当其任意子节点的功能
    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;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 定义叶子点
    class LeafEntity : public I_Component {
    public:
    	LeafEntity(string s) : name(s) {}
    	virtual void Operation(){
    		cout << "this is leaf:" << name<< endl;
    	}
    
    private:
    	string name;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这时候当我们想获取某一个节点下的详细信息,只需要调用抽象接口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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    组合模式的思考

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

    优势:

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

    劣势:

    • 如果本质上叶子节点差异巨大时,很难抽象,只能通过适配器or桥接的形式给叶子节点提供适配接口,代码会变得难以理解;
  • 相关阅读:
    Java -- 每日一问:谈谈 Spring Bean 的生命周期和作用域?
    linux设备模型:设备及设备节点创建过程分析
    Chrome自动升级了,找不到最新版本的webdriver怎么办?
    Leetcode:349. 两个数组的交集【题解超详细】
    java毕业设计论文题目SSM框架车库停车计费系统|停车场
    前端面试宝典React篇06 setState 是同步更新还是异步更新?
    脉脉上的 “前端三大浪漫“ 是个啥?
    css网格布局
    go语言实现LeetCode59 螺旋矩阵Ⅱ
    澳大利亚昆士兰大学ARC信息复原力培训中心博士后
  • 原文地址:https://blog.csdn.net/u013052326/article/details/126089095