享元模式,又叫Flyweight,属于对象性能模式中的一种,主要解决系统中大量的细粒度的对象而带来不必要的系统开销,主要是指内存方面的开销。

模式定义

运用共享技术有效地支持大量细粒度的对象。 —《设计模式》 GoF

模式动机

系统中有大量的对象时,而且这些对象有些之间是相同的,或者说可以把这些对象分为几类,这种情况就可以使用相同的一类对象合并成使用相同的一个对象,因此系统就由之前很多重复的几类对象变为几个互不相同的对象,大大节约了系统的内存开销。
如何辨别这些对象是相同的?可以传入一个键值作为唯一标识码,如果这个键值相同,则返回其对应的对象,无需重复创建。

需要注意的事项,由于在内存中是多个业务共享了一个对象,为了避免改变这个对象,因此这个对象应该是只读的。

代码分析

假如现在需要画10个圆,现在有3中颜色,正常的设计应该是每一个圆对应一个对象,然后分别画出,但是由于每个圆的颜色只有3中,因此只要是颜色相同的圆,我们就可以使用同一个对象来创建,因此只需要3个对象即可。

画圆类

包括一个画圆的函数和string类型的颜色

class Circle
{
public:
	Circle(std::string color);
	~Circle();
	std::string color;
	virtual void shape();
};

Circle::Circle(std::string color)
{
	this->color = color;
}

void Circle::shape()
{
	std::cout << "shape circle : " << this->color << std::endl;
}

画圆工厂类

使用享元模式产生一个画圆的对象,使用一个map容器来存储所有互不相同的对象,这些对象通过颜色来区分,因此使用颜色作为键值

class ShapeFactory
{
private:
	/* 创建一个对象池存储所有的对象,这是一个散列表,通过color找到对应的对象 */
	std::map <std::string, Circle* >  Circlepool;
public:
	ShapeFactory();
	~ShapeFactory();

	Circle* createCircle(std::string color);
};

Circle* ShapeFactory::createCircle(std::string color)
{
	std::map <std::string, Circle*> ::iterator item = Circlepool.find(color);
	/* 查找是否已经创建过了 */
	if (item != Circlepool.end())
	{
		return Circlepool[color];
	}
	else
	{
		std::cout << "create new circle \n";
		Circle *circle = new Circle(color);
		Circlepool[color] = circle;
		return circle;
	}
}

main函数

先构造一个工厂,再调用createCircle产生对象,是否产生了新对象有内部的享元模式进行判断

int main()
{
	ShapeFactory *shapefactory = new ShapeFactory;
	Circle *circle1 = shapefactory->createCircle("red");
	circle1->shape();

	Circle *circle2 = shapefactory->createCircle("red");
	circle2->shape();

	Circle *circle3 = shapefactory->createCircle("blue");
	circle3->shape();
	
}

运行结果:

可以看到,创建第二个红色圆形的时候并没有创建新的对象,而是使用了第一个创建的对象,而创建第三份白色圆的时候又创建了新的对象,这就是使用享元模式创建对象的过程。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

适配器模式 上一篇
抽象工厂 下一篇