這篇文章將為大家詳細(xì)講解有關(guān)如何理解Flyweight模式,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

[Flyweight模式]
官方描述:
意圖
運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對(duì)象。
適用性
1、一個(gè)應(yīng)用程序使用了大量的對(duì)象。
2、完全由于使用大量的對(duì)象,造成很大的存儲(chǔ)開銷。
3、對(duì)象的大多數(shù)狀態(tài)都可變?yōu)橥獠繝顟B(tài)。
4、如果刪除對(duì)象的外部狀態(tài),那么可以用相對(duì)較少的共享對(duì)象取代很多組對(duì)象。
5、應(yīng)用程序不依賴于對(duì)象標(biāo)識(shí)。由于Flyweight 對(duì)象可以被共享,對(duì)于概念上明顯有別的對(duì)象,標(biāo)識(shí)測(cè)試將返回真值。
我的描述:
在開始設(shè)計(jì)類的時(shí)候,很自然的根據(jù)現(xiàn)實(shí)情況把某些屬性作為類的一部分,例如設(shè)計(jì)一個(gè)圖書的管理系統(tǒng),每本書都有出版社、編號(hào)、作者、價(jià)錢等的屬性,所以這個(gè)書的類可以這樣設(shè)計(jì):
class Book
{
public:
string GetPublish() {return m_publishCompany;}
string GetWriter() {return m_writer;}
int GetBookID() {return m_bookID;}
int GetPrice() {return m_price;}
string GetName() {return m_name;}
void SetPublish(string &s) {m_publishCompany = s;}
void SetWriter(string &s) {m_writer = s;}
void SetBookID(int id) {m_bookID = id;}
void SetPrice(int price) {m_price = price;}
void SetName(string &s) {m_name = s;}
private:
string m_publishCompany; // 出版社
string m_writer; // 作者
int m_bookID; // 書籍編號(hào)
int m_price; // 價(jià)錢
string m_name; // 書名
};
這非常自然。但是隨著系統(tǒng)的開發(fā)和試運(yùn)行,這種設(shè)計(jì)就表現(xiàn)出一些不足的地方了,例如一般圖書會(huì)非常多,成千上萬本,在這些書中可能會(huì)有相同的出版社或者相同的作者,那對(duì)每本書來說就會(huì)重復(fù)了,也就是浪費(fèi)了一些重復(fù)的空間。
如果每本書都耗費(fèi)一些空間,那整個(gè)軟件系統(tǒng)所耗費(fèi)的空間是不可想象的。所以,我們就要想辦法來解決這個(gè)問題。
高明的面向?qū)ο笤O(shè)計(jì)者就想出了這個(gè)辦法,把一些相同的屬性(把它叫做“享元”)提取出來,并用一個(gè)表來管理(池),這就是Flyweight模式的思想所在。好了,我們現(xiàn)在來看看示意圖:
這里的ConcreteFlyweight就是需要共享的屬性(享元),例如上面的出版社和作者,這里的UnsharedConcreteFlyweight就是
不用共享的屬性(書籍編號(hào)和價(jià)錢)。
想象一下系統(tǒng)里面Book類的使用:
1、先看看不用共享模式:
Book book1, book2, book3;
book1.SetPublish("機(jī)械工業(yè)出版社");
book1.SetWriter("候捷");
book1.SetBookID(0000);
book1.SetPrice(20);
book1.SetName("C++好野");
book2.SetPublish("人民郵電出版社");
book2.SetWriter("候捷");
book2.SetBookID(0001);
book2.SetPrice(30);
book2.SetName("C++是好勁");
book3.SetPublish("機(jī)械工業(yè)出版社");
book3.SetWriter("一雨田");
book3.SetBookID(0002);
book3.SetPrice(50);
book3.SetName("C++無得頂,我是鐵頭功...");
這里有兩個(gè)“機(jī)械工業(yè)出版社”和兩個(gè)“候捷”,重復(fù)了。如果使用共享模式的話,這里的浪費(fèi)就可以避免了。
別看這里只有兩個(gè),想象一下成千上萬本書時(shí)的空間浪費(fèi)...
2、使用共享模式,把出版社和作者兩個(gè)屬性作為享元(Fly~~Weight)
PublishFlyweightFactory pff;
WriterFlyweightFactory wff;
Book book1, book2, book3;
book1.SetPublish(pff.GetPublish("機(jī)械工業(yè)出版社")->GetName());
book1.SetWriter(wff.GetWriter("候捷")->GetName());
book1.SetBookID(0000);
book1.SetPrice(20);
book1.SetName("C++好野");
book2.SetPublish(pff.GetPublish("人民郵電出版社")->GetName());
book2.SetWriter(wff.GetWriter("候捷")->GetName());
book2.SetBookID(0001);
book2.SetPrice(30);
book2.SetName("C++是好勁");
book3.SetPublish(pff.GetPublish("機(jī)械工業(yè)出版社")->GetName());
book3.SetWriter(wff.GetWriter("一雨田")->GetName());
book3.SetBookID(0002);
book3.SetPrice(50);
book3.SetName("C++無得頂,我是鐵頭功...");
為什么使用了PublishFlyweightFactory和WriterFlyweightFactory之后就可以節(jié)省空間了呢?
奧妙就在于GetPublish和GetWriter的實(shí)現(xiàn):
PublishFlyweight* GetPublish(string key)
{
PublishFlyweight *p;
mapPublish::iterator it;
it = mapPublish.find(key);
// 存在這個(gè)Writer
if(it != mapPublish.end() )
p = it;
else
{// 插入這個(gè)PublishFlyweight
p = new PublishFlyweight(key);
mapPublish[key] = p;
}
return p;
}
GetWriter的實(shí)現(xiàn)大同小異,這里就不列出來了,請(qǐng)看詳細(xì)代碼里的實(shí)現(xiàn)。
下面是完整的代碼,可以在一個(gè)CPP文件里編譯使用,由于使用CSDN提供的插入代碼功能會(huì)使得整段拷貝有點(diǎn)問題,所以這里還是直接給出代碼,并標(biāo)注顏色,方便大家的拷貝:
// Flyweight.cpp
#pragma warning(disable: 4786)
#include <iostream>
#include <map>
#include <string>
using namespace std;
class Book
{
public:
string GetPublish() {return *m_publishCompany;}
string GetWriter() {return *m_writer;}
int GetBookID() {return m_bookID;}
int GetPrice() {return m_price;}
string GetName() {return m_name;}
void SetPublish(string *s) {m_publishCompany = s;}
void SetWriter(string *s) {m_writer = s;}
void SetBookID(int id) {m_bookID = id;}
void SetPrice(int price) {m_price = price;}
void SetName(string &s) {m_name = s;}
private:
string *m_publishCompany; // 出版社
string *m_writer; // 作者
int m_bookID; // 書籍編號(hào)
int m_price; // 價(jià)錢
string m_name; // 書名
};
class PublishFlyweight
{
public:
PublishFlyweight(string s)
{
m_name = s;
}
string GetName()
{
return m_name;
}
private:
string m_name;
};
class PublishFlyweightFactory
{
public:
PublishFlyweight* GetPublish(string key)
{
PublishFlyweight *p;
map<string, PublishFlyweight*>::iterator it;
it = mapPublish.find(key);
// 存在這個(gè)出版社
if(it != mapPublish.end() )
{
// 這里可能有點(diǎn)難懂,請(qǐng)查閱STL的幫助文檔
// 其實(shí)second就是指 map<string, PublishFlyweight*> 的 PublishFlyweight*
p = (*it).second;
cout << "已經(jīng)有這個(gè)出版社: " << p->GetName() << " 你節(jié)省了" << strlen(p->GetName().c_str()) << "字節(jié)的空間" << endl;
}
else
{// 插入這個(gè)PublishFlyweight
p = new PublishFlyweight(key);
mapPublish[key] = p;
}
return p;
}
private:
map<string, PublishFlyweight*> mapPublish;
};
class WriterFlyweight
{
public:
WriterFlyweight(string s)
{
m_name = s;
}
string GetName()
{
return m_name;
}
private:
string m_name;
};
class WriterFlyweightFactory
{
public:
WriterFlyweight* GetWriter(string key)
{
WriterFlyweight *p;
map<string, WriterFlyweight*>::iterator it;
it = mapWriter.find(key);
// 存在這個(gè)Writer
if(it != mapWriter.end() )
{
// 這里可能有點(diǎn)難懂,請(qǐng)查閱STL的幫助文檔
// 其實(shí)second就是指 map<string, WriterFlyweight*> 的 WriterFlyweight*
p = (*it).second;
cout << "已經(jīng)有這個(gè)作者名字: " << p->GetName() << " 你節(jié)省了" << strlen(p->GetName().c_str()) << "字節(jié)的空間" << endl;
}
else
{// 插入這個(gè)PublishFlyweight
p = new WriterFlyweight(key);
mapWriter[key] = p;
}
return p;
}
private:
map<string, WriterFlyweight*> mapWriter;
};
void ShowBookInfo(Book book)
{
cout << "書名:" << book.GetName() << endl;
cout << "編號(hào):" << book.GetBookID() << endl;
cout << "價(jià)錢:" << book.GetPrice() << endl;
cout << "出版:" << book.GetPublish() << endl;
cout << "作者:" << book.GetWriter() << endl;
cout << endl;
}
void main()
{
PublishFlyweightFactory pff;
WriterFlyweightFactory wff;
Book book1, book2, book3;
book1.SetPublish( &(pff.GetPublish("機(jī)械工業(yè)出版社")->GetName()) );
book1.SetWriter( &(wff.GetWriter("候捷")->GetName()) );
book1.SetBookID(0000);
book1.SetPrice(20);
book1.SetName(string("<<C++好野>>"));
ShowBookInfo(book1);
book2.SetPublish( &(pff.GetPublish("人民郵電出版社")->GetName()) );
book2.SetWriter( &(wff.GetWriter("候捷")->GetName()) );
book2.SetBookID(0001);
book2.SetPrice(30);
book2.SetName(string("<<C++是好勁>>"));
ShowBookInfo(book2);
book3.SetPublish( &(pff.GetPublish("機(jī)械工業(yè)出版社")->GetName()) );
book3.SetWriter( &(wff.GetWriter("一雨田")->GetName()) );
book3.SetBookID(0002);
book3.SetPrice(50);
book3.SetName(string("<<C++無得頂,我是鐵頭功...>>"));
ShowBookInfo(book3);
}
好了,如果你能看到這里,希望能幫助你把Flyweight模式理解了,但好還是動(dòng)手把代碼拷貝到VC 里,編譯運(yùn)行一下,你可以看到Flyweight模式幫你節(jié)省了多少空間。謝謝!
標(biāo)題名稱:如何理解Flyweight模式-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)URL:http://www.chinadenli.net/article30/deedpo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、網(wǎng)站建設(shè)、Google、微信公眾號(hào)、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容