您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何理解Flyweight模式,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
[Flyweight模式]
官方描述:
意圖
運用共享技術有效地支持大量細粒度的對象。
適用性
1、一個應用程序使用了大量的對象。
2、完全由于使用大量的對象,造成很大的存儲開銷。
3、對象的大多數(shù)狀態(tài)都可變?yōu)橥獠繝顟B(tài)。
4、如果刪除對象的外部狀態(tài),那么可以用相對較少的共享對象取代很多組對象。
5、應用程序不依賴于對象標識。由于Flyweight 對象可以被共享,對于概念上明顯有別的對象,標識測試將返回真值。
我的描述:
在開始設計類的時候,很自然的根據(jù)現(xiàn)實情況把某些屬性作為類的一部分,例如設計一個圖書的管理系統(tǒng),每本書都有出版社、編號、作者、價錢等的屬性,所以這個書的類可以這樣設計:
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; // 書籍編號
int m_price; // 價錢
string m_name; // 書名
};
這非常自然。但是隨著系統(tǒng)的開發(fā)和試運行,這種設計就表現(xiàn)出一些不足的地方了,例如一般圖書會非常多,成千上萬本,在這些書中可能會有相同的出版社或者相同的作者,那對每本書來說就會重復了,也就是浪費了一些重復的空間。
如果每本書都耗費一些空間,那整個軟件系統(tǒng)所耗費的空間是不可想象的。所以,我們就要想辦法來解決這個問題。
高明的面向?qū)ο笤O計者就想出了這個辦法,把一些相同的屬性(把它叫做“享元”)提取出來,并用一個表來管理(池),這就是Flyweight模式的思想所在。好了,我們現(xiàn)在來看看示意圖:
這里的ConcreteFlyweight就是需要共享的屬性(享元),例如上面的出版社和作者,這里的UnsharedConcreteFlyweight就是
不用共享的屬性(書籍編號和價錢)。
想象一下系統(tǒng)里面Book類的使用:
1、先看看不用共享模式:
Book book1, book2, book3;
book1.SetPublish("機械工業(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("機械工業(yè)出版社");
book3.SetWriter("一雨田");
book3.SetBookID(0002);
book3.SetPrice(50);
book3.SetName("C++無得頂,我是鐵頭功...");
這里有兩個“機械工業(yè)出版社”和兩個“候捷”,重復了。如果使用共享模式的話,這里的浪費就可以避免了。
別看這里只有兩個,想象一下成千上萬本書時的空間浪費...
2、使用共享模式,把出版社和作者兩個屬性作為享元(Fly~~Weight)
PublishFlyweightFactory pff;
WriterFlyweightFactory wff;
Book book1, book2, book3;
book1.SetPublish(pff.GetPublish("機械工業(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("機械工業(yè)出版社")->GetName());
book3.SetWriter(wff.GetWriter("一雨田")->GetName());
book3.SetBookID(0002);
book3.SetPrice(50);
book3.SetName("C++無得頂,我是鐵頭功...");
為什么使用了PublishFlyweightFactory和WriterFlyweightFactory之后就可以節(jié)省空間了呢?
奧妙就在于GetPublish和GetWriter的實現(xiàn):
PublishFlyweight* GetPublish(string key)
{
PublishFlyweight *p;
mapPublish::iterator it;
it = mapPublish.find(key);
// 存在這個Writer
if(it != mapPublish.end() )
p = it;
else
{// 插入這個PublishFlyweight
p = new PublishFlyweight(key);
mapPublish[key] = p;
}
return p;
}
GetWriter的實現(xiàn)大同小異,這里就不列出來了,請看詳細代碼里的實現(xiàn)。
下面是完整的代碼,可以在一個CPP文件里編譯使用,由于使用CSDN提供的插入代碼功能會使得整段拷貝有點問題,所以這里還是直接給出代碼,并標注顏色,方便大家的拷貝:
// 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; // 書籍編號
int m_price; // 價錢
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);
// 存在這個出版社
if(it != mapPublish.end() )
{
// 這里可能有點難懂,請查閱STL的幫助文檔
// 其實second就是指 map<string, PublishFlyweight*> 的 PublishFlyweight*
p = (*it).second;
cout << "已經(jīng)有這個出版社: " << p->GetName() << " 你節(jié)省了" << strlen(p->GetName().c_str()) << "字節(jié)的空間" << endl;
}
else
{// 插入這個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);
// 存在這個Writer
if(it != mapWriter.end() )
{
// 這里可能有點難懂,請查閱STL的幫助文檔
// 其實second就是指 map<string, WriterFlyweight*> 的 WriterFlyweight*
p = (*it).second;
cout << "已經(jīng)有這個作者名字: " << p->GetName() << " 你節(jié)省了" << strlen(p->GetName().c_str()) << "字節(jié)的空間" << endl;
}
else
{// 插入這個PublishFlyweight
p = new WriterFlyweight(key);
mapWriter[key] = p;
}
return p;
}
private:
map<string, WriterFlyweight*> mapWriter;
};
void ShowBookInfo(Book book)
{
cout << "書名:" << book.GetName() << endl;
cout << "編號:" << book.GetBookID() << endl;
cout << "價錢:" << 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("機械工業(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("機械工業(yè)出版社")->GetName()) );
book3.SetWriter( &(wff.GetWriter("一雨田")->GetName()) );
book3.SetBookID(0002);
book3.SetPrice(50);
book3.SetName(string("<<C++無得頂,我是鐵頭功...>>"));
ShowBookInfo(book3);
}
好了,如果你能看到這里,希望能幫助你把Flyweight模式理解了,但最好還是動手把代碼拷貝到VC 里,編譯運行一下,你可以看到Flyweight模式幫你節(jié)省了多少空間。謝謝!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。