所谓享元模式就是运行共享技术有效地支持大量细粒度对象的复用。系统使用少量对象,而且这些都比较相似,状态变化小,可以实现对象的多次复用。
共享模式是支持大量细粒度对象的复用,所以享元模式要求能够共享的对象必须是细粒度对象。
在了解享元模式之前我们先要了解两个概念:内部状态、外部状态。
内部状态:在享元对象内部不随外界环境改变而改变的共享部分。
外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态。
由于享元模式区分了内部状态和外部状态,所以我们可以通过设置不同的外部状态使得相同的对象可以具备一些不同的特性,而内部状态设置为相同部分。在我们的程序设计过程中,我们可能会需要大量的细粒度对象来表示对象,如果这些对象除了几个参数不同外其他部分都相同,这个时候我们就可以利用享元模式来大大减少应用程序当中的对象。如何利用享元模式呢?这里我们只需要将他们少部分的不同的部分当做参数移动到类实例的外部去,然后再方法调用的时候将他们传递过来就可以了。这里也就说明了一点:内部状态存储于享元对象内部,而外部状态则应该由客户端来考虑。
===========================================================================
关于内部状态和外部状态的理解,比如创建若干奥迪A6轿车,要求它的长宽高都是相同的,但必须允许颜色和功率不同。
然后car对象使用享元对象封装车的长宽高数据称为内部数据,颜色和功率称为外部数据。
===========================================================================
享元模式存在如下几个角色:
Flyweight: 抽象享元类。所有具体享元类的超类或者接口,通过这个接口,Flyweight可以接受并作用于外部专题
ConcreteFlyweight: 具体享元类。指定内部状态,为内部状态增加存储空间。
UnsharedConcreteFlyweight: 非共享具体享元类。指出那些不需要共享的Flyweight子类。
FlyweightFactory: 享元工厂类。用来创建并管理Flyweight对象,它主要用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory就会提供一个已经创建的Flyweight对象或者新建一个(如果不存在)。
享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。
UML图的模板:
#include "stdafx.h"
#include<stdlib.h>
#include <string>
#include <list>
#include<iostream>
using namespace std;
typedef std::string STATE;
class Flyweight
{
public:
virtual ~Flyweight(){}
STATE GetIntrinsicState();
virtual void Operation(STATE& ExtrinsicState) = 0;
protected:
Flyweight(const STATE& state):m_State(state){}
private:
STATE m_State;
};
class FlyweightFactory
{
public:
FlyweightFactory(){}
~FlyweightFactory();
Flyweight* GetFlyweight(const STATE& key);
private:
list<Flyweight*> m_listFlyweight;
};
class ConcreateFlyweight: public Flyweight
{
public:
ConcreateFlyweight(const STATE& state): Flyweight(state){}
virtual ~ConcreateFlyweight(){}
virtual void Operation(STATE& ExtrinsicState);
};
inline STATE Flyweight::GetIntrinsicState()
{
return m_State;
}
FlyweightFactory::~FlyweightFactory()
{
list<Flyweight*>::iterator iter1, iter2, temp;
for (iter1 = m_listFlyweight.begin(), iter2 = m_listFlyweight.end();
iter1 != iter2;
)
{
temp = iter1;
++iter1;
delete (*temp);
}
m_listFlyweight.clear();
}
Flyweight* FlyweightFactory::GetFlyweight(const STATE& key)
{
std::list<Flyweight*>::iterator iter1, iter2;
for (iter1 = m_listFlyweight.begin(), iter2 = m_listFlyweight.end();
iter1 != iter2;
++iter1)
{
if ((*iter1)->GetIntrinsicState() == key)
{
std::cout << "The Flyweight:" << key << " already exits" << std::endl;
return (*iter1);
}
}
std::cout << "Creating a new Flyweight:" << key << std::endl;
Flyweight* flyweight = new ConcreateFlyweight(key);
m_listFlyweight.push_back(flyweight);
}
void ConcreateFlyweight::Operation(STATE& ExtrinsicState)
{
}
int main()
{
FlyweightFactory flyweightfactory;
flyweightfactory.GetFlyweight("hello");
flyweightfactory.GetFlyweight("world");
flyweightfactory.GetFlyweight("hello");
system("pause");
return 0;
}
使用例子:
#include "stdafx.h"
#include <iostream>
#include <map>
using namespace std;
class Character
{
public:
virtual void SetSize(int, int) = 0;
virtual void Display() = 0;
protected:
Character(){};
char m_chSymbol;
int m_nWeight;
int m_nHeight;
};
class CharacterA : public Character
{
public:
CharacterA()
{
this->m_chSymbol = 'A';
this->m_nWeight = 100;
this->m_nHeight = 200;
}
void SetSize(int nWeight, int nHeight)
{
this->m_nWeight = nWeight;
this->m_nHeight = nHeight;
}
void Display()
{
cout << "CharacterA:" << m_chSymbol << "(" << m_nWeight << "," << m_nHeight << ")" << endl;
}
};
class CharacterB : public Character
{
public:
CharacterB()
{
this->m_chSymbol = 'B';
this->m_nWeight = 100;
this->m_nHeight = 200;
}
void SetSize(int nWeight, int nHeight)
{
this->m_nWeight = nWeight;
this->m_nHeight = nHeight;
}
void Display()
{
cout << "CharacterB:" << m_chSymbol << "(" << m_nWeight << "," << m_nHeight << ")" << endl;
}
};
class CharacterFactory
{
public:
CharacterFactory()
{
m_mChar.insert(make_pair<char, Character*>('A', new CharacterA));
m_mChar.insert(make_pair<char, Character*>('B', new CharacterB));
}
Character* GetCharacter(char chIn)
{
map<char, Character*>::iterator it = m_mChar.find(chIn);
if (it != m_mChar.end())
{
return (Character*)it->second;
}
return NULL;
}
private:
std::map<char, Character*> m_mChar;
};
int _tmain(int argc, _TCHAR* argv[])
{
CharacterFactory* pFactory = new CharacterFactory;
//内部状态 存储在享元对象内部并且不会随环境改变而改变
Character* ch1 = pFactory->GetCharacter('A');
ch1->Display();
//外部状态 客户端保存
Character* ch2 = pFactory->GetCharacter('B');
ch2->SetSize(500, 800);
ch2->Display();
return 0;
}