一、UML图
二、包含的角色
Flyweight类 , 同一享元对象可在许多不同情景中使用。 享元中存储的状态被称为 “内在状态”。 传递给享元方法的状态被称为 “外在状态”。
FlyweightFactory类,工厂会根据参数在之前已创建的享元中进行查找,如果找到满足条件 的享元就将其返回; 如果没有找到就根据参数新建享元。
Context类,通常情况下,原始对象的行为会保留在享元类中。 因此调用享元方法必须提供部分外在状态作为参数。 但你也可将行为移动到情景类中, 然后将连入的享元作为单纯的数据对象。
三、特点
享元模式只是一种优化。 在应用该模式之前, 你要确定程序中存在与大量类似对象同时占用内存相关的内存消耗问题, 并且确保该问题无法使用其他更好的方式来解决。
四、代码实现
Flyweight类
#pragma once
#include <iostream>
class Flyweight
{
public:
Flyweight(int innerState) : _innerState(innerState)
{
std::cout <<"Flyweight()"<<std::endl;
}
~Flyweight()
{
std::cout <<"~Flyweight()"<<std::endl;
}
void Operation(int outerState)
{
std::cout <<"Flyweight Operation->>"<<_innerState << std::endl;
}
private:
int _innerState;
};
FlyweightFactory类
#include "Flyweight.h"
#include <unordered_map>
class FlyweightFactory
{
public:
static FlyweightFactory &GetInstance()
{
static FlyweightFactory ins;
return ins;
}
private:
FlyweightFactory()
{
std::cout <<"FlyweightFactory()"<<std::endl;
}
public:
~FlyweightFactory()
{
std::cout <<"~FlyweightFactory()"<<std::endl;
for (auto i : _flyweightMap)
{
delete i.second;
}
_flyweightMap.clear();
}
Flyweight* GetFlyweight(int innerState)
{
Flyweight *f = nullptr;
auto it = _flyweightMap.find(innerState);
if (it == _flyweightMap.end())
{
f = new Flyweight(innerState);
_flyweightMap.insert({ innerState, f });
return f;
}
else
{
return it->second;
}
}
private:
std::unordered_map<int, Flyweight *> _flyweightMap;
};
Context类
#pragma once
#include <iostream>
#include "Flyweight.h"
#include "FlyweightFactory.h"
class Context
{
public:
Context(int innerState,int outState)
{
std::cout <<"Context()"<<std::endl;
_flyweight = FlyweightFactory::GetInstance().GetFlyweight(innerState);
_outState=outState;
}
~Context()
{
std::cout <<"~Context()"<<std::endl;
}
void Operation()
{
std::cout <<"Context Operation"<<std::endl;
_flyweight->Operation(_outState);
}
private:
Flyweight* _flyweight;
int _outState;
};
main
#include "Context.h"
int main()
{
int innerState = 1;
int outState = 2;
Context* c = new Context(innerState,outState);
c->Operation();
delete c;
return 0;
}