一、什么是享元模式
享元模式是一种结构型设计模式,它通过共享对象来减少内存使用和提高性能。在享元模式中,对象被分为两种类型:内部状态和外部状态。内部状态是可以共享的,而外部状态是不可共享的。
二、享元模式的实现原理
- 创建一个抽象享元类,定义了具体享元类需要实现的方法。
- 创建具体享元类,实现抽象享元类定义的方法,并定义内部状态和外部状态。
- 创建一个享元工厂类,用于管理和创建享元对象。该工厂类维护一个享元池,用于存储已经创建的享元对象。
- 在客户端中,通过享元工厂类获取或创建享元对象,并将外部状态传递给享元对象。
注意:通过使用享元模式,可以有效地减少对象的数量,提高系统的性能和内存利用率。但需要注意的是,享元模式适用于对象的内部状态较多且相似的情况,如果对象的内部状态较少或者差异较大,则可能无法获得明显的性能提升。
三、享元模式的应用场景
1.绘图工具的应用。
在绘图工具中,用户可以选择不同的形状(如圆形、矩形、三角形等)进行绘制。如果每次用户选择一个形状时都创建一个新的对象,那么会消耗大量的内存。而使用享元模式,可以共享相同形状的对象,只需存储一份形状的状态信息,并在需要时进行复用。
举个例子,假设用户在绘图工具中选择了一个红色的圆形进行绘制。当用户再次选择红色圆形时,可以直接使用之前创建的对象,而不需要再次创建一个新的对象。这样可以减少内存使用,并提高性能。
2.文本编辑器中的字符对象的应用。
在文本编辑器中,每个字符都可以看作是一个对象。如果每个字符都创建一个新的对象,那么对于大文本文件来说,将会消耗大量的内存。而使用享元模式,可以共享相同字符的对象,只需存储一份字符的状态信息,并在需要时进行复用。
3. 量化交易系统的设计
在量化交易系统中,可能存在大量的交易策略对象,这些对象可能具有相同的属性和行为,只是在具体的参数上有所不同。如果每个策略对象都独立创建,会占用大量的内存资源。而使用享元模式,可以将相同的属性和行为抽象出来,作为共享的部分,而将不同的参数作为外部状态,在需要时动态传入。
具体应用方面,享元模式可以在以下几个方面发挥作用:
交易策略对象的共享:将相同的交易策略对象共享,减少内存占用。例如,如果有多个策略对象使用相同的技术指标计算方法,可以将这部分计算方法抽象出来作为共享的部分。
缓存数据对象:在量化交易系统中,可能需要频繁地获取历史数据、实时行情等信息。使用享元模式可以将这些数据对象缓存起来,避免重复创建和销毁,提高系统性能。
共享工具类:在量化交易系统中,可能存在一些通用的工具类,例如日期处理、数学计算等。这些工具类可以使用享元模式进行共享,避免重复创建和加载,提高系统效率。
总之,享元模式在量化交易系统中的应用可以减少内存占用、提高系统性能,并且可以通过共享对象来优化系统设计。
四、享元模式的代码实现
//+------------------------------------------------------------------+
//| structure |
//+------------------------------------------------------------------+
//
// | FlyweightFactory |o------------------>*| Flyweight |
// |---------------------------| |--------------------------|
// +->|GetFlyweight(key) | |Operation(extrinsic_state)|
// | | if(flyweight[key] exists) | ^
// | | return existing flyweight| |
// | | else | +---------------+----------------+
// | | create new flyweight | | |
// | | add it to the pool of | +->| ConcreteFlyweight | +->|UnsharedConcreteFlyweight |
// | | flyweights | | |--------------------------| | |--------------------------|
// | | return the new flyweight | | |Operation(extrinsic_state)| | |Operation(extrinsic_state)|
// | | |--------------------------| | |--------------------------|
// | | |intrinsic_state | | |all_state |
// | | |
//|Client|------------------------------+---------------------------------+
//
//+------------------------------------------------------------------+
//| diagram — sharing of flyweights |
//+------------------------------------------------------------------+
//
// |aClient| |aClient|
// |-------| |-------|
// | * | +-----------|-* * |
// | | |
// +------------|------|---------------|--------------+
// |flyweights | | | |
// |pool | | | |
// | v v v |
//|aFlyweightFactory| | |ConcreteFlyweight| |ConcreteFlyweight| |
//|-----------------| | |-----------------| |-----------------| |
//|flyweights *---|----+-----|-->|intrinsic_state | +->|intrinsic_state | |
// | | | |
// +-----|-------------------------+ |
// +--------------------------------------------------+
//
//+------------------------------------------------------------------+
//| interface — for patterns |
//+------------------------------------------------------------------+
interface ClientInterface
{
string Output(void);
void Run(void);
};
//+------------------------------------------------------------------+
//| interface — for patterns |
//+------------------------------------------------------------------+
void Run(ClientInterface* client)
{
printf("---\n%s",client.Output());
client.Run();
delete client;
}
// 声明了一个接口,蝇量级可以通过该接口接收
// 并根据外在状态行事
interface Flyweight
{
void Operation(int extrinsic_state);
};
//+------------------------------------------------------------------+
//| class — flyweight pair |
//+------------------------------------------------------------------+
class Pair
{
protected:
string key;
Flyweight* value;
public:
Pair(void);
Pair(string, Flyweight*);
~Pair(void);
Flyweight* Value(void);
string Key(void);
};
//+------------------------------------------------------------------+
//| flyweight pair > constructor > default |
//+------------------------------------------------------------------+
Pair::Pair(void)
{
}
//+------------------------------------------------------------------+
//| flyweight pair > constructor > key — value |
//+------------------------------------------------------------------+
Pair::Pair(string a_key,Flyweight *a_value):
key(a_key),
value(a_value)
{
}
//+------------------------------------------------------------------+
//| flyweight pair > destructor |
//+------------------------------------------------------------------+
Pair::~Pair(void)
{
delete value;
}
//+------------------------------------------------------------------+
//| flyweight pair > get — key |
//+------------------------------------------------------------------+
string Pair::Key(void)
{
return key;
}
//+------------------------------------------------------------------+
//| flyweight pair > get — value |
//+------------------------------------------------------------------+
Flyweight* Pair::Value(void)
{
return value;
}
//+------------------------------------------------------------------+
//| class — flyweight dictionary |
//+------------------------------------------------------------------+
class Dictionary
{
protected:
Pair* pairs[];
public:
Dictionary(void);
~Dictionary(void);
void Add(string,Flyweight*);
bool Has(string);
Flyweight* operator[](string);
protected:
int Find(string);
};
//+------------------------------------------------------------------+
//| flyweight dictionary > constructor |
//+------------------------------------------------------------------+
Dictionary::Dictionary(void)
{
}
//+------------------------------------------------------------------+
//| flyweight dictionary > destructor |
//+------------------------------------------------------------------+
Dictionary::~Dictionary(void)
{
int total=ArraySize(pairs);
for(int i=0; i<total; i++)
{
Pair* ipair=pairs[i];
if(CheckPointer(ipair))
{
delete ipair;
}
}
}
//+------------------------------------------------------------------+
//| flyweight dictionary > find key |
//+------------------------------------------------------------------+
int Dictionary::Find(string key)
{
int total=ArraySize(pairs);
for(int i=0; i<total; i++)
{
Pair* ipair=pairs[i];
if(ipair.Key()==key)
{
return i;
}
}
return -1;
}
//+------------------------------------------------------------------+
//| flyweight dictionary > has key |
//+------------------------------------------------------------------+
bool Dictionary::Has(string key)
{
return (Find(key)>-1)?true:false;
}
//+------------------------------------------------------------------+
//| flyweight dictionary > add key — value |
//+------------------------------------------------------------------+
void Dictionary::Add(string key,Flyweight *value)
{
int size=ArraySize(pairs);
ArrayResize(pairs,size+1);
pairs[size]=new Pair(key,value);
}
//+------------------------------------------------------------------+
//| flyweight dictionary > get value at key |
//+------------------------------------------------------------------+
Flyweight* Dictionary::operator[](string key)
{
int find=Find(key);
return (find>-1)?pairs[find].Value():NULL;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| participants > concrete flyweight |
//+------------------------------------------------------------------+
class ConcreteFlyweight:public Flyweight
{
public:
void Operation(int extrinsic_state);
protected:
int intrinsic_state;
};
//+------------------------------------------------------------------+
//| participants > concrete flyweight > operation |
//+------------------------------------------------------------------+
void ConcreteFlyweight::Operation(int extrinsic_state)
{
intrinsic_state=extrinsic_state;
printf("intrinsic state: %d",intrinsic_state);
}
//+------------------------------------------------------------------+
//| participants > unshared concrete flyweight |
//+------------------------------------------------------------------+
class UnsharedConcreteFlyweight:public Flyweight
{
protected:
int all_state;
public:
void Operation(int extrinsic_state);
};
//+------------------------------------------------------------------+
//| participants > unshared concrete flyweight > operation |
//+------------------------------------------------------------------+
void UnsharedConcreteFlyweight::Operation(int extrinsic_state)
{
all_state=extrinsic_state;
printf("all state: %d",all_state);
}
//+------------------------------------------------------------------+
//| participants > flyweight factory |
//+------------------------------------------------------------------+
class FlyweightFactory
{
protected:
Dictionary pool;
public:
FlyweightFactory(void);
Flyweight* Flyweight(string key);
};
//+------------------------------------------------------------------+
//| participants > flyweight factory > constructor |
//+------------------------------------------------------------------+
FlyweightFactory::FlyweightFactory(void)
{
pool.Add("1",new ConcreteFlyweight);
pool.Add("2",new ConcreteFlyweight);
pool.Add("3",new ConcreteFlyweight);
}
//+------------------------------------------------------------------+
//| participants > flyweight factory > get flyweight |
//+------------------------------------------------------------------+
Flyweight* FlyweightFactory::Flyweight(string key)
{
if(!pool.Has(key)) //pool has no such key
{
pool.Add(key,new ConcreteFlyweight()); //create new key—flyweight pair
}
return pool[key]; //return flyweight at key
}
//+------------------------------------------------------------------+
//| participants > client |
//+------------------------------------------------------------------+
class Client:public ClientInterface
// maintains a reference to flyweight(s)
// computes or stores the extrinsic state of flyweight(s)
{
public:
string Output();
void Run();
};
string Client::Output(void)
{
return __FUNCTION__;
}
//+------------------------------------------------------------------+
//| collaborations |
//+------------------------------------------------------------------+
void Client::Run(void)
{
int extrinsic_state=7;
Flyweight* flyweight;
FlyweightFactory factory;
//---the extrinsic state is relayed to all flyweights
flyweight=factory.Flyweight("1");
flyweight.Operation(extrinsic_state);
flyweight=factory.Flyweight("10");
flyweight.Operation(extrinsic_state);
//---
flyweight=new UnsharedConcreteFlyweight();
flyweight.Operation(extrinsic_state);
delete flyweight;
}
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---structural
Run(new Client);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| output |
//+------------------------------------------------------------------+
// Flyweight::Client::Output
// intrinsic state: 7
// intrinsic state: 7
// all state: 7