享元模式
定义:
运用共享技术支持大量细粒度的复用
优点:
(1)减少内存中对象中的数量,使得相同或相似对象只保留一份
(2)外部状态相对独立不影响内部状态
缺点:
(1)系统变得复杂了,需要分离内部状态和外部状态
使用范围:
系统存在大量的相同相似对象,且这些对象可以组成对象池
如:围棋黑白棋子
结构:
flyweight_pattern:享元抽象类,棋子的基类
black_igo:黑子 ; white_igo:白子; coord:棋子位置(内部状态)
factory_flyweight_pattern:享元对象池
实现:
namespace structural_pattern
{
class coord
{
public:
coord(int x, int y) :x(x), y(y) {};
int get_x() { return x; }
int get_y() { return y; }
private:
int x;
int y;
};
class flyweight_pattern
{
public:
virtual void set_coord(int x, int y) = 0;
virtual void disp() = 0;
protected:
std::vector<coord>vec_coord;
};
class black_igo : public flyweight_pattern
{
void set_coord(int x, int y) override
{
coord crd{ x,y };
vec_coord.push_back(crd);
}
void disp() override
{
for each(auto itr in vec_coord)
{
std::cout << "black -- " << itr.get_x() << " " << itr.get_y() << std::endl;
}
}
};
class white_igo : public flyweight_pattern
{
void set_coord(int x,int y) override
{
coord crd{ x,y };
vec_coord.push_back(crd);
}
void disp() override
{
for each(auto itr in vec_coord)
{
std::cout << "white -- " << itr.get_x() << " " << itr.get_y() << std::endl;
}
}
};
class factory_flyweight_pattern
{
public:
factory_flyweight_pattern()
{
static flyweight_pattern* b = new black_igo();
static flyweight_pattern* a = new white_igo();;
flyweight.insert(std::pair<int, flyweight_pattern*>(1, b));
flyweight.insert(std::pair<int, flyweight_pattern*>(2, a));
}
flyweight_pattern*get_igo(int key)
{
if (flyweight.find(key) != flyweight.end())
{
return flyweight.at(key);
}
throw new std::exception("no element");
}
private:
std::map<int, flyweight_pattern*> flyweight;
};
}
测试:
基于GoogleTest 的单元测试框架;框架可参考如下网址:
https://www.cnblogs.com/jycboy/p/gtest_catalog.html
using namespace structural_pattern;
TEST(test_flyweight_pattern_get_igo, success_add)
{
factory_flyweight_pattern fac;
fac.get_igo(1)->set_coord(1,2);
fac.get_igo(1)->set_coord(2,4);
fac.get_igo(1)->disp();
fac.get_igo(2)->set_coord(1, 3);
fac.get_igo(2)->set_coord(2, 6);
fac.get_igo(2)->disp();
}
总结
(1)需要额外创建享元对象池类,通过map方式来保存享元对象
(2)通过key值获取真实的享元对象
(3)分离享元对象的内部和外部状态
(4)通过对象池方式实现对象复用,关注对象生命周期