c++设计模式之组合模式 学习笔记

组合模式适合生活中<成树状分布的组织结构>的设计。
为了便于直观的理解,这里不用专业术语来解释(因为刚开始学的时候被搞烦了,感觉这东西入门不易解释的太晦涩太复杂),直接举个生活中的实例,列上代码,然后简单的分析一下实例代码。
比如你在学校,开学了,你们学校计划组织开学典礼。假设计划最初是由校长制定的,那消息是如何传达到学生的?通常来说,校长一般是不会直接告诉学生的,而是告知各个院系的院长,然后各院长再分别告知本院的各个班级的辅导员,最后由辅导员传达消息给学生。
这个消息传达的过程就是一个树状结构,适合用组合来进行设计。代码如下:

#include<iostream>
#include<vector>
#include<memory>
#include<algorithm>

//抽象根节点,该节点拥有增添子节点,删除子节点的作用,并可以显示节点名称
class AbstractRootNode
{
public:
	AbstractRootNode(std::string name):nodeName(name){}
	virtual void add(AbstractRootNode *p) {}
	virtual void remove(AbstractRootNode *p) {}
	virtual void noticeMessage() = 0;
public:
	std::string nodeName;
};
struct Funt
{
public:
	Funt(std::string nameT) :nameR(nameT) {}
	bool operator()(std::shared_ptr<AbstractRootNode> (p))
	{
		return (nameR==(p->nodeName));
	}
public:
	std::string nameR;
};
class ConcreteRootNode:public AbstractRootNode
{
public:

	ConcreteRootNode(std::string name) :AbstractRootNode(name) {}
	void add(AbstractRootNode *p)
	{
		auto it = std::find_if(nodeVec.begin(), nodeVec.end(), Funt(p->nodeName));
		if (it == nodeVec.end()) 
			nodeVec.push_back(std::shared_ptr<AbstractRootNode>(p)); //强转一下
	}
	void remove(AbstractRootNode *p)
	{
		auto it = std::find_if(nodeVec.begin(), nodeVec.end(), Funt(p->nodeName));
		if (it != nodeVec.end()) nodeVec.erase(it); 
	}
	void noticeMessage()
	{
		for (auto it = nodeVec.begin(); it != nodeVec.end(); it++)
		{
			(*it)->noticeMessage();
		}
	}
private:
	std::vector<std::shared_ptr<AbstractRootNode>> nodeVec;

};
class ConcreteLeafNode :public AbstractRootNode
{
public:

	ConcreteLeafNode(std::string name) :AbstractRootNode(name) {}
	void noticeMessage()
	{
		std::cout << "我是" << nodeName.c_str() << ",我已经知道消息了" << std::endl;
	}
};
void main()
{
	AbstractRootNode* A = new ConcreteRootNode("校长");

	AbstractRootNode* B1 = new ConcreteRootNode("计算机院长");
	AbstractRootNode* B2 = new ConcreteRootNode("电气院长");
	AbstractRootNode* B3 = new ConcreteRootNode("土木院长");

	AbstractRootNode* C11 = new ConcreteRootNode("计算机一班辅导员");
	AbstractRootNode* C12 = new ConcreteRootNode("计算机二班辅导员");
	AbstractRootNode* C21 = new ConcreteRootNode("电气一班辅导员");
	AbstractRootNode* C22 = new ConcreteRootNode("电气二班辅导员");
	AbstractRootNode* C31 = new ConcreteRootNode("土木一班辅导员");
	AbstractRootNode* C32 = new ConcreteRootNode("土木二班辅导员");

	AbstractRootNode*D111 = new ConcreteLeafNode("计算机一班张三");
	AbstractRootNode*D112 = new ConcreteLeafNode("计算机一班李四");
	AbstractRootNode*D121 = new ConcreteLeafNode("计算机二班张三");
	AbstractRootNode*D122 = new ConcreteLeafNode("计算机二班李四");
	AbstractRootNode*D211 = new ConcreteLeafNode("电气一班张三");
	AbstractRootNode*D212 = new ConcreteLeafNode("电气一班李四");
	AbstractRootNode*D221 = new ConcreteLeafNode("电气二班张三");
	AbstractRootNode*D222 = new ConcreteLeafNode("电气二班李四");
	AbstractRootNode*D311 = new ConcreteLeafNode("土木一班张三");
	AbstractRootNode*D312 = new ConcreteLeafNode("土木一班李四");
	AbstractRootNode*D321 = new ConcreteLeafNode("土木一班张三");
	AbstractRootNode*D322 = new ConcreteLeafNode("土木一班李四");

	C11->add(D111);
	C11->add(D112);
	C12->add(D121);
	C12->add(D122);
	C21->add(D211);
	C21->add(D212);
	C22->add(D221);
	C22->add(D222);
	C31->add(D311);
	C31->add(D312);
	C32->add(D321);
	C32->add(D322);

	B1->add(C11);
	B1->add(C12);
	B2->add(C21);
	B2->add(C22);
	B3->add(C31);
	B3->add(C32);


	A->add(B1);
	A->add(B2);
	A->add(B3);
	A->remove(B2);

	A->noticeMessage();
	system("pause");
	return;
}

结果如下:在这里插入图片描述如图,该学校所有学生都通知到了。【为了测试remove功能,我们调用了A->remove(B2),所以电气的学生都没有接到通知】

我们直接看代码,其实很清晰,我的例子中一共只有3个类:一个抽象的根节点类AbstractRootNode,一个具体的根节点类ConcreteRootNode,和一个叶子节点类ConcreteLeafNode。
它们分别代表什么呢?
具体的根节点类——代表了你的树状结构中,会拥有子节点的节点,即所有拥有子节点的节点原型都是它
叶子节点类——代表了树状结构的最后一级,它没有子节点,它是最底层节点
抽象根节点:其实应该叫抽象节点,你可以理解为各种节点类的基类,为了实现多态的。

到了这里,你想象一下——一个树状结构中,我们所有的节点都有了表示(最底层的用ConcreteLeafNode,其余所有的用ConcreteRootNode)。剩下的就是它们之间的连接了,这个显然更简单,你只需要从下到上(不按顺序也行,就是有点乱),依次的将所有子节点add到它的根节点上就行了。

就是这么简单。😄

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值