1定义
使用共享对象可有效的支持大量细粒度的对象
2类图
角色分析
Flyweight抽象享元角色,一个产品的抽象,定义内部状态和外部状态的接口或者实现
ConcreteFlyweight具体享元角色,实现抽象角色定义的业务。注:内部状态处理和环境无关
unsharedConcreteFlyweight不可共享的享元角色,不存在外部状态或者安全要求,不能够使用共性技术的对象,该对象一般不会出现在享元工厂中
Flyweight享元工厂,就是构造一个池容器,同时提供从翅中获得对象的方法
3实现
#pragma once
#include<hash_map>
#include<iostream>
using namespace std; class Flyweight
{
private:
//内部状态
string intrinsic;
protected:
//外部状态
const string extrainsic;
public:
Flyweight(string _ex)
:extrainsic ( _ex)
{
} //定义业务操作
virtual void operate(){}
string getIntrinsic()
{
return intrinsic;
}
void setIntrinsic(string _in)
{
intrinsic = _in;
}
}; class ConcreteFlyweight1 :public Flyweight
{
public:
ConcreteFlyweight1(string ex)
:Flyweight(ex)
{} void operate()
{
//根据外部逻辑进行业务处理
cout << "1根据外部逻辑进行业务处理!" << endl;
}
};
class ConcreteFlyweight2 :public Flyweight
{
public:
ConcreteFlyweight2(string ex)
:Flyweight(ex)
{} void operate()
{
//根据外部逻辑进行业务处理
cout << "2根据外部逻辑进行业务处理!" << endl;
}
};
class FlyweightFactory
{
private:
static hash_map<string, Flyweight*> pool;
public:
Flyweight* getFlyweight(string ex)
{
hash_map<string, Flyweight*>::iterator it = pool.find(ex);
if (it == pool.end())
{
cout << "Creat Flyweight1" << endl;
pool[ex] = new ConcreteFlyweight1(ex);
}
return pool[ex];
}
}; hash_map<string, Flyweight*> FlyweightFactory::pool = hash_map<string,Flyweight*>();
class Client
{
public:
void operator()()
{
FlyweightFactory ff;
Flyweight * pf = ff.getFlyweight("lianglihui");
pf->operate();
}
};
4应用
①优点
是一个简单的模式,可以大大减少程序创建的对象,降低内存占用,增强性能
②缺点
提高系统复杂性,需要分离状态,且外部状态不应该随着内部状态的改变而改变
③使用场景
系统中存在大量的相似对象
细粒度的对象都具有较接近的外部状态,而内部状态和环境无关。
需要缓冲池的场景
5扩展
① 线程安全问题,因为共享对象比较少,多个线程同时去访问通过外部状态对其内部状态访问就出现了线程安全问题。--》使用享元模式时,保证享元对象足够多,同时处理掉线程安全问题就好
②性能问题
优化:将外部状态封装成类,通过桥梁模式进行嫁接,减少耦合,提高效率/使用系统内置类型作为外部状态
(ps因为池中检测会有调用消耗)
6对象池vs享元模式
享元模式可以实现对象池
对象池着重在对象的复用,池中的每个对象都是可替换的,从同一个池中获得A对象和B对象对客户端来讲是完全相同的,主要解决复用。
享元模式侧重共享问题,如何建立多个可共享的细粒度对象则是其关注的重点。