C++ 学习笔记(25)Composite Pattern

版权声明:如若转载,注明出处即可 https://blog.csdn.net/nishisiyuetian/article/details/82783831

Composite Pattern

组合模式

考虑一个系统,存在层次管理关系,例如公司内董事长之下,有多个经理,每个经理之下都由若干个部门,每个部分都若干个员工,如果采用面向对象的思想来设计这样一个树状的系统?

建立统一基类对象:Component

分类:内节点(枝干),外节点(叶子)

特点:(1)内节点可以有孩子,外节点不可以有孩子;(2)内节点的孩子可以是内节点,也可以是孩子

区别:和数据结构中的递归定义树对比,叶子是不可以拥有孩子的,叶子不可能成为内节点,这是一开始就设计好的,哪些是叶子,哪些是枝干,对象之间的组合只需要枝干添加孩子即可。但这也成为瓶颈之一,因为如果日后叶子需要新添部门,或者需要再次细分,改动不易,解决思路有 II ——(1)初始设计中,决定不会再细分的部分才定义为叶子,一定会细分或者可能细分的部分一定要定义为枝干(2)如果后续对叶子一定要再次细分,只需要替换叶子的父节点的孩子即可,并把原来的孩子删除,不过这样就需要保存父节点,较浪费空间。

大致模式如下:

基类定义:

class Component {
public:
	virtual ~Component() = default;

	// 添加孩子(附属)
	virtual void addChild(Component *const child) = 0;

	// 删除孩子
	virtual void removeChild(Component *const child) = 0;

	// 获取第 index 个孩子
	virtual Component* getChild(const int index) = 0;

	// 访问自己以及自己的孩子
	virtual void visit() = 0;
} ;

叶子定义:

class Leaf : public Component {
public:
	virtual void addChild(Component *const child) {
		/* forbidden */
	}
	virtual void removeChild(Component *const child) {
		/* forbidden */
	}
	virtual Component* getChild(const int index) {
		/* forbidden */
		return nullptr;
	}
	virtual void visit() {
		/*
			访问叶子节点
		*/
	}
} ;

枝干定义:

class Trunk : public Component {
public:
	virtual void addChild(Component *const child) {
		/* find 去重 */
		childs.emplace_back(child);
	}
	virtual void removeChild(Component *const child) {
		/* 
			找到 child, 然后 erase, 以及 delete child
		 */
	}
	virtual Component* getChild(const int index) {
		return index >= childs.size() ? nullptr : childs[index];
	}
	virtual void visit() {
		/*
			遍历容器, 逐个访问孩子
		*/
	}
private:
	std::vector<Component*> childs;
} ;

适用场景:

(1)树形结构系统

(2)需要忽略内节点和外节点差异

猜你喜欢

转载自blog.csdn.net/nishisiyuetian/article/details/82783831