组合模式——现代C++设计模式

使用场景

组合模式的目标是让单个对象和对象的集合存在相同的接口

基础组合模式的实现代码

#include<iostream>
#include<vector>
using namespace std;

struct GraphicObject {
	virtual void draw() = 0;
};
struct Circle :GraphicObject {
	void draw() override
	{
		cout << "Circle" << endl;
	}
};
struct group :GraphicObject {
	string name;
	vector<GraphicObject*> objects;

	group(const string& name) :name{ name } {

	}
	void draw() override
	{
		cout << "group  " << name << "  contains: " << endl;
		for (auto&& o : objects) o->draw();
	}
};


int main() {
	group root("root");
	Circle c1, c2;
	root.objects.push_back(&c1);
	root.objects.push_back(&c2);


	group gp1("gp1");
	Circle c3, c4;
	gp1.objects.push_back(&c3);
	gp1.objects.push_back(&c4);
	root.objects.push_back(&gp1);

	root.draw();
	return 0;
}

可以观察到,group是circle的集合,但是他们都有相同的接口:draw(),这是因为group 中存在一个指向基类向量的指针,所以group也可以是group的集合。

更复杂的组合模式

上个例子中只包括了集合包含元素,集合包含集合,可能有人好奇如果想要元素包含集合该怎么办呢?

实现代码

#include<iostream>
#include<vector>
using namespace std;
struct NeuronLayer;
struct Neuron;

template<typename Self>
struct SomeNeurons { //用来将属性转换为Neuron
	virtual  SomeNeurons* begin() = 0;
	virtual  SomeNeurons* end() = 0;
	template<typename T>void connect_to(T& other) {
		for (Neuron& from : *static_cast<Self*>(this)) { //基于范围的循环
			for (Neuron& to : other) {
				from.out.push_back(&to);
				to.in.push_back(&from);
			}
		}
	}
};

struct Neuron:public SomeNeurons<Neuron> //继承自模板类,以Neuron作为模板
{
	vector<Neuron*>in, out; 
	unsigned int id;
	Neuron()
	{
		static int id = 1; 
		this->id = id++;
	}
	Neuron* begin() override { return this; }
	Neuron* end() override{ return this+1; }
};

struct NeuronLayer :vector<Neuron> {	//模板类继承,这样NeuronLayer是一个向量
	int count;
	NeuronLayer(int count = 0) :count{count} {
		
		while (count-- > 0) {
			emplace_back(Neuron{});//emplace_back是vector继承来的函数
		}
	}

	template<typename T>void connect_to(T& other) {
		for (Neuron& from : *static_cast<NeuronLayer*>(this)) {
			for (Neuron& to : other) {
				from.out.push_back(&to);
				to.in.push_back(&from);
			}
		}
	}

};

int main() {
	Neuron neuron, neuron1;
	NeuronLayer layer, layer1;
	neuron.connect_to(neuron1);
	neuron.connect_to(layer);
	layer.connect_to(neuron);
	layer.connect_to(layer1);

	return 0;
}

上个例子中layer是neuron向量继承得到的,通过调用connect_to,既可以实现层与层的连接,也可以实现神经元与神经元的连接,使用到了模板成员函数、模板类

本例中还有到了范围循环,被循环的对象需要存在begin、end函数,由于NeuronLayer是由模板类vector继承而来,所以无需定义,Neuron则需要通过以下方法定义:

Neuron* begin() override { return this; }
Neuron* end() override{ return this+1; }

模板类

模板类的形式为

template<typename Self>
class{
};

具体类型Self可以通过运行中的参数指定

总结

组合模式通过显式使用接口或鸭子类型(仿照实现begin、end伪装成集合)实现单个类型与类型集合的转换接口

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值