C++設(shè)計模式之享元模式(Flyweight)
享元模式顧名思義就是羽量級模式或者蠅級模式,形容體量小的應(yīng)用,該模式主要的設(shè)計目的是為了迎合系統(tǒng)大量相似數(shù)據(jù)的應(yīng)用而生,減少用于創(chuàng)建和操作相似的細碎對象所花費的成本。大量的對象會消耗高內(nèi)存,享元模式給出了一個解決方案,即通過共享對象來減少內(nèi)存負載。
作用
通過復(fù)用相同的對象來減少對象的創(chuàng)建數(shù)量,創(chuàng)建更小的對象組,并通過共享實現(xiàn)重用。通過歸類,將對象的屬性分為內(nèi)蘊狀態(tài)和外蘊狀態(tài)。要創(chuàng)建具體的享元對象,我們需要創(chuàng)建一個享元工廠來統(tǒng)一管理對象的生成和輸出,享元工廠是實現(xiàn)享元模式的關(guān)鍵。
舉個例子,享元模式可以看成是一個工具箱,而享元對象就是工具箱內(nèi)的具體的工具,我們在使用工具的時候,不必每回臨時的制造工具,而是直接從工具箱里找到工具進行使用,這樣就大大節(jié)約了制造工具的成本時間和工具占用的空間。
享元模式比較迷惑在于理解兩種狀態(tài)的分類,內(nèi)蘊狀態(tài)是對象本身的屬性,在生成對象以后一般不會進行改變,比如工具中的屬性:名字、大小、重量等,還有就是我們一般需要一個關(guān)鍵性的屬性作為其區(qū)別于其他對象的key,如工具的話我們可以把名稱作為找到工具的唯一標識。
外蘊狀態(tài)是對象的外部描述,是每個對象的可變部分,比如對工具的使用地點、使用時間、使用人、工作內(nèi)容的描述,這些屬性不屬于對象本身,而是根據(jù)每回使用情況進行變化的,這就需要制作成接口進行外部調(diào)用,而外蘊狀態(tài)的維護是由調(diào)用者維護的,對象內(nèi)不進行維護。
類視圖
實現(xiàn)
//Flyweight class tool { public: //內(nèi)蘊狀態(tài) string name; int nSize; int nWeight; public: //外蘊狀態(tài) 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() { //外蘊狀態(tài) 由調(diào)用者維護 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)和復(fù)合享元(unshare)
復(fù)合享元也既是unshareFlyweight,其不再是單一的對象,而是一系列對象的組合,他們的關(guān)系由原來的一對一的關(guān)系,變成了一對多的關(guān)系。
舉例說明,如【DP】中比較經(jīng)典的圍棋的例子,單享元模式下,我們對圍棋的顏色種類進行共享,再棋盤的工廠類中只需包含黑白兩顆棋子,就能完成對棋盤下棋的整個操作,而不用對每一個棋子進行操作。但是有一天需求增加了對勝負的要求,那么就需要對棋子的坐標進行記錄,對于黑白兩種顏色的棋子,相對應(yīng)的就會有相同顏色棋子的坐標數(shù)組容器,like:map<string,vector<Point>> 這樣的結(jié)構(gòu)。
應(yīng)用場景
- 需要創(chuàng)建大量對象時;
- 大多數(shù)對象可以分為內(nèi)蘊和外蘊狀態(tài);
- 應(yīng)用程序需要使用多種對象,并且重復(fù)使用;
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
c語言for、while和do-while循環(huán)之間的區(qū)別
大家好,本篇文章主要講的是c語言for、while和do-while循環(huán)之間的區(qū)別,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01C++實現(xiàn)LeetCode(6.字型轉(zhuǎn)換字符串)
這篇文章主要介紹了C++實現(xiàn)LeetCode(6.字型轉(zhuǎn)換字符串),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07C++數(shù)據(jù)結(jié)構(gòu)之單鏈表
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)之單鏈表,鏈表是由一個個結(jié)點鏈結(jié)成的。結(jié)點包括數(shù)據(jù)域和指針域兩部分,數(shù)據(jù)域用來存儲數(shù)據(jù)元素的信息,指針域用來存儲下一個結(jié)點的地址,更詳細內(nèi)容請需要的小伙伴參考下面文章內(nèi)容2022-01-01