享元模式顧名思義就是羽量級模式或者蠅級模式,形容體量小的應用,該模式主要的設計目的是為了迎合系統大量相似數據的應用而生,減少用於創建和操作相似的細碎對象所花費的成本。大量的對象會消耗高記憶體,享元模式給出了一個解決方案,即通過共用對象來減少記憶體負載。 作用 通過復用相同的對象來減少對象的創建數量,創建 ...
享元模式顧名思義就是羽量級模式或者蠅級模式,形容體量小的應用,該模式主要的設計目的是為了迎合系統大量相似數據的應用而生,減少用於創建和操作相似的細碎對象所花費的成本。大量的對象會消耗高記憶體,享元模式給出了一個解決方案,即通過共用對象來減少記憶體負載。
作用
通過復用相同的對象來減少對象的創建數量,創建更小的對象組,並通過共用實現重用。通過歸類,將對象的屬性分為內蘊狀態和外蘊狀態。要創建具體的享元對象,我們需要創建一個享元工廠來統一管理對象的生成和輸出,享元工廠是實現享元模式的關鍵。
舉個例子,享元模式可以看成是一個工具箱,而享元對象就是工具箱內的具體的工具,我們在使用工具的時候,不必每回臨時的製造工具,而是直接從工具箱里找到工具進行使用,這樣就大大節約了製造工具的成本時間和工具占用的空間。
享元模式比較迷惑在於理解兩種狀態的分類,內蘊狀態是對象本身的屬性,在生成對象以後一般不會進行改變,比如工具中的屬性:名字、大小、重量等,還有就是我們一般需要一個關鍵性的屬性作為其區別於其他對象的key,如工具的話我們可以把名稱作為找到工具的唯一標識。
外蘊狀態是對象的外部描述,是每個對象的可變部分,比如對工具的使用地點、使用時間、使用人、工作內容的描述,這些屬性不屬於對象本身,而是根據每回使用情況進行變化的,這就需要製作成介面進行外部調用,而外蘊狀態的維護是由調用者維護的,對象內不進行維護。
類視圖
實現
//Flyweight
class tool
{
public:
//內蘊狀態
string name;
int nSize;
int nWeight;
public:
//外蘊狀態
virtual int used(string person, string work)=0;
}
//ConcreteFlyweight
class hammer : public tool
{
public:
hammer():name("hammer"){}
int used(string person, string work)
{
cout<< person <<"use"<<name<<"to" << work;
}
}
//ConcreteFlyweight
class screwdriver : public tool
{
screwdriver():name("screwdriver"){}
int used(string person, string work)
{
cout<< person <<"use"<< name << " to" << work;
}
}
//ConcreteFlyweight
class saw : public tool
{
saw():name("saw"){}
int used(string person, string work)
{
cout<< person <<"use"<< name <<"to" << work;
}
}
//FlyweightFactory
class toolbox
{
public:
toolbox();
virtual ~toolbox()
{
map<string,tool*>::iterator it = m_tool.find(toolname);
for(it=m_tool.begin();it!=m_tool.end();it++)
{
delete it.second;
}
}
tool* GetTool(string toolname)
{
map<string,tool*>::iterator it = m_tool.find(toolname);
if(it != m_tool.end())
{
return (tool*) it.second;
}
else
{
tool* tooltemp= NULL;
if(toolname == "hammer")
tooltemp = new hammer();
else if(toolname == "screwdriver")
tooltemp = new screwdriver();
else if(toolname == "saw")
tooltemp = new saw();
if(tooltemp !=NULL)
m_tool.insert(make_pair<string,tool*>(toolname,tooltemp));
return tooltemp;
}
}
private:
map<string,tool*> m_tool;
}
int main()
{
//外蘊狀態 由調用者維護
string person1 = "zhangsan";
string person2 = "lisi";
string work1 = "make desk";
string work2 = "repair bike";
//生成工廠
toolbox tBox;
//獲取享元
tool* tool1 = tBox.GetTool("hammer");
tool1.used(person1,work1);
tool* tool2 = tBox.GetTool("screwdriver");
tool2.used(person2,work2);
}
單享元(share)和複合享元(unshare)
複合享元也既是unshareFlyweight,其不再是單一的對象,而是一系列對象的組合,他們的關係由原來的一對一的關係,變成了一對多的關係。
舉例說明,如【DP】中比較經典的圍棋的例子,單享元模式下,我們對圍棋的顏色種類進行共用,再棋盤的工廠類中只需包含黑白兩顆棋子,就能完成對棋盤下棋的整個操作,而不用對每一個棋子進行操作。但是有一天需求增加了對勝負的要求,那麼就需要對棋子的坐標進行記錄,對於黑白兩種顏色的棋子,相對應的就會有相同顏色棋子的坐標數組容器,like:map<string,vector<Point>>
這樣的結構。
應用場景
- 需要創建大量對象時;
- 大多數對象可以分為內蘊和外蘊狀態;
- 應用程式需要使用多種對象,並且重覆使用;