Flyweight Pattern with C++
享元模式 C++实现
享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例数据除了几个参数外基本都是相同的。有时就能够大幅度地减少实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。
这种模式可以运用共享技术有效地支持大量细粒度的对象。适合具有缓冲池的场景。
首先我们要分清楚享元模式的内部状态和外部状态。
内部状态:在享元对象内部并且不会随环境改变而改变的共享部分,可以称为是享元对象的内部状态,比如base class中的member
外部状态:而随环境改变而改变的,取决于应用环境,或是实时数据,这些不可以共享的东西就是外部状态了。比如存在的map的key值
内部状态存储于ConcreteFlyweight对象之中;而外部状态则由Client对象存储或计算。
####当用户调用Flyweight对象的操作时,将该状态传递给它。
####外部状态有一个factory,负责维护外部状态,并把外部状态和class放入container中。
#include
#include
#include
#include
#include
using namespace std;
class Flyweight
{
public:
//操作外部状态extrinsicState
virtual void Operation(const string& extrinsicState)=0;
string GetIntrinsicState()
{
return this->_intrinsicState;
}
virtual ~Flyweight(){}
protected:
Flyweight(string intrinsicState)
{
this->_intrinsicState = intrinsicState;
}
private:
//内部状态,也可以放在ConcreteFlyweight中
string _intrinsicState;
};
class ConcreteFlyweight:public Flyweight
{
public:
virtual void Operation(const string& extrinsicState)
{
cout << this->GetIntrinsicState() << endl;
cout << extrinsicState << endl;
}
ConcreteFlyweight(string intrinsicState):Flyweight(intrinsicState){}
~ConcreteFlyweight(){}
};
class UnsharedConcreteFlyweight:public Flyweight
{
public:
virtual void Operation(const string& extrinsicState)
{
cout << extrinsicState << endl;
}
UnsharedConcreteFlyweight(string intrinsicState):Flyweight(intrinsicState){}
~UnsharedConcreteFlyweight(){}
};
class FlyweightFactory
{
public:
FlyweightFactory(){}
~FlyweightFactory(){}
//获得一个请求的Flyweight对象
Flyweight* GetFlyweight(string key)
{
if(m_mapFly.find(key)!=m_mapFly.end())
{
return m_mapFly[key];
}
//Flyweight* fly = new ConcreteFlyweight(key);
Flyweight* fly = new UnsharedConcreteFlyweight(key);
this->m_mapFly.insert(pair<string,Flyweight*>(key,fly));
return fly;
}
//获取容器中存储的对象数量
void GetFlyweightCount()
{
cout << this->m_mapFly.size() << endl;
}
protected:
private:
//保存内部状态对象的容器
hash_map<string,Flyweight*> m_mapFly;
};
int main()
{
//外部状态extrinsicState
string extrinsicState = "ext";
//工厂对象,工厂对象
FlyweightFactory* fc = new FlyweightFactory();
Flyweight* fly = fc->GetFlyweight("hello");
fly = fc->GetFlyweight("hello1");
fly = fc->GetFlyweight("hello");
//应用外部状态
fly->Operation("hello3");
fc->GetFlyweightCount();
return 0;
}
</code></pre>
线程环境下,必须使用锁变量。结局这种问题的方式,就是使用外部类来当做key值,但是这又会出现另一个问题:维护一个container。class的效率明显比string类型低。
参考:
[http://blog.csdn.net/lcl_data/article/details/8974679](http://blog.csdn.net/lcl_data/article/details/8974679)
[http://msdn.microsoft.com/zh-cn/library/th79x793.aspx](http://msdn.microsoft.com/zh-cn/library/th79x793.aspx)