生活随笔
收集整理的這篇文章主要介紹了
设计模式C++实现(9)——享元模式
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
? ?軟件領(lǐng)域中的設(shè)計(jì)模式為開發(fā)人員提供了一種使用專家設(shè)計(jì)經(jīng)驗(yàn)的有效途徑。設(shè)計(jì)模式中運(yùn)用了面向?qū)ο缶幊陶Z言的重要特性:封裝、繼承、多態(tài),真正領(lǐng)悟設(shè)計(jì)模式的精髓是可能一個(gè)漫長的過程,需要大量實(shí)踐經(jīng)驗(yàn)的積累。最近看設(shè)計(jì)模式的書,對(duì)于每個(gè)模式,用C++寫了個(gè)小例子,加深一下理解。主要參考《大話設(shè)計(jì)模式》和《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》(DP)兩本書。本文介紹享元模式的實(shí)現(xiàn)。
??????? 舉個(gè)圍棋的例子,圍棋的棋盤共有361格,即可放361個(gè)棋子?,F(xiàn)在要實(shí)現(xiàn)一個(gè)圍棋程序,該怎么辦呢?首先要考慮的是棋子棋盤的實(shí)現(xiàn),可以定義一個(gè)棋子的類,成員變量包括棋子的顏色、形狀、位置等信息,另外再定義一個(gè)棋盤的類,成員變量中有個(gè)容器,用于存放棋子的對(duì)象。下面給出代碼表示:
????????棋子的定義,當(dāng)然棋子的屬性除了顏色和位置,還有其他的,這里略去。這兩個(gè)屬性足以說明問題。
[cpp]?view plaincopy print?
?? enum?PieceColor?{BLACK,?WHITE};?? ?? struct?PiecePos?? {?? ????int?x;?? ????int?y;?? ????PiecePos(int?a,?int?b):?x(a),?y(b)?{}?? };?? ?? class?Piece?? {?? protected:?? ????PieceColor?m_color;??? ????PiecePos?m_pos;??????? public:?? ????Piece(PieceColor?color,?PiecePos?pos):?m_color(color),?m_pos(pos)?{}?? ????~Piece()?{}?? ????virtual?void?Draw()?{}?? };?? class?BlackPiece:?public?Piece?? {?? public:?? ????BlackPiece(PieceColor?color,?PiecePos?pos):?Piece(color,?pos)?{}?? ????~BlackPiece()?{}?? ????void?Draw()?{?cout<<"繪制一顆黑棋"<<endl;}?? };?? class?WhitePiece:?public?Piece?? {?? public:?? ????WhitePiece(PieceColor?color,?PiecePos?pos):?Piece(color,?pos)?{}?? ????~WhitePiece()?{}?? ????void?Draw()?{?cout<<"繪制一顆白棋"<<endl;}?? };??
????????棋盤的定義:
[cpp]?view plaincopy print?
class?PieceBoard?? {?? private:?? ????vector<Piece*>?m_vecPiece;??? ????string?m_blackName;??? ????string?m_whiteName;??? public:?? ????PieceBoard(string?black,?string?white):?m_blackName(black),?m_whiteName(white){}?? ????~PieceBoard()?{?Clear();?}?? ????void?SetPiece(PieceColor?color,?PiecePos?pos)??? ????{?? ????????Piece?*?piece?=?NULL;?? ????????if(color?==?BLACK)??? ????????{????? ????????????piece?=?new?BlackPiece(color,?pos);??? ????????????cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";?? ????????????piece->Draw();??? ????????}?? ????????else?? ????????{????? ????????????piece?=?new?WhitePiece(color,?pos);?? ????????????cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";?? ????????????piece->Draw();?? ????????}?? ????????m_vecPiece.push_back(piece);???? ????}?? ????void?Clear()??? ????{?? ????????int?size?=?m_vecPiece.size();?? ????????for(int?i?=?0;?i?<?size;?i++)?? ????????????delete?m_vecPiece[i];?? ????}?? };??
????????客戶的使用方式如下:
[cpp]?view plaincopy print?
int?main()?? {?? ????PieceBoard?pieceBoard("A","B");?? ????pieceBoard.SetPiece(BLACK,?PiecePos(4,?4));?? ????pieceBoard.SetPiece(WHITE,?PiecePos(4,?16));?? ????pieceBoard.SetPiece(BLACK,?PiecePos(16,?4));?? ????pieceBoard.SetPiece(WHITE,?PiecePos(16,?16));?? }??
???????可以發(fā)現(xiàn),棋盤的容器中存放了已下的棋子,而每個(gè)棋子包含棋子的所有屬性。一盤棋往往需要含上百顆棋子,采用上面這種實(shí)現(xiàn),占用的空間太大了。如何改進(jìn)呢?用享元模式。其定義為:運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對(duì)象。
????????在圍棋中,棋子就是大量細(xì)粒度的對(duì)象。其屬性有內(nèi)在的,比如顏色、形狀等,也有外在的,比如在棋盤上的位置。內(nèi)在的屬性是可以共享的,區(qū)分在于外在屬性。因此,可以這樣設(shè)計(jì),只需定義兩個(gè)棋子的對(duì)象,一顆黑棋和一顆白棋,這兩個(gè)對(duì)象含棋子的內(nèi)在屬性;棋子的外在屬性,即在棋盤上的位置可以提取出來,存放在單獨(dú)的容器中。相比之前的方案,現(xiàn)在容器中僅僅存放了位置屬性,而原來則是棋子對(duì)象。顯然,現(xiàn)在的方案大大減少了對(duì)于空間的需求。
? ? ? ?關(guān)注PieceBoard 的容器,之前是vector<Piece*> m_vecPiece,現(xiàn)在是vector<PiecePos> m_vecPos。這里是關(guān)鍵。
???????棋子的新定義,只包含內(nèi)在屬性:
[cpp]?view plaincopy print?
?? enum?PieceColor?{BLACK,?WHITE};?? ?? struct?PiecePos?? {?? ????int?x;?? ????int?y;?? ????PiecePos(int?a,?int?b):?x(a),?y(b)?{}?? };?? ?? class?Piece?? {?? protected:?? ????PieceColor?m_color;??? public:?? ????Piece(PieceColor?color):?m_color(color)?{}?? ????~Piece()?{}?? ????virtual?void?Draw()?{}?? };?? class?BlackPiece:?public?Piece?? {?? public:?? ????BlackPiece(PieceColor?color):?Piece(color)?{}?? ????~BlackPiece()?{}?? ????void?Draw()?{?cout<<"繪制一顆黑棋\n";?}?? };?? class?WhitePiece:?public?Piece?? {?? public:?? ????WhitePiece(PieceColor?color):?Piece(color)?{}?? ????~WhitePiece()?{}?? ????void?Draw()?{?cout<<"繪制一顆白棋\n";}?? };??
????????相應(yīng)棋盤的定義為:
[cpp]?view plaincopy print?
class?PieceBoard?? {?? private:?? ????vector<PiecePos>?m_vecPos;??? ????Piece?*m_blackPiece;????????? ????Piece?*m_whitePiece;????????? ????string?m_blackName;?? ????string?m_whiteName;?? public:?? ????PieceBoard(string?black,?string?white):?m_blackName(black),?m_whiteName(white)?? ????{?? ????????m_blackPiece?=?NULL;?? ????????m_whitePiece?=?NULL;?? ????}?? ????~PieceBoard()?{?delete?m_blackPiece;?delete?m_whitePiece;}?? ????void?SetPiece(PieceColor?color,?PiecePos?pos)?? ????{?? ????????if(color?==?BLACK)?? ????????{?? ????????????if(m_blackPiece?==?NULL)???? ????????????????m_blackPiece?=?new?BlackPiece(color);????? ????????????cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";?? ????????????m_blackPiece->Draw();?? ????????}?? ????????else?? ????????{?? ????????????if(m_whitePiece?==?NULL)?? ????????????????m_whitePiece?=?new?WhitePiece(color);?? ????????????cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";?? ????????????m_whitePiece->Draw();?? ????????}?? ????????m_vecPos.push_back(pos);?? ????}?? };??
???????客戶的使用方式一樣,這里不重復(fù)給出,現(xiàn)在給出享元模式的UML圖,以圍棋為例。棋盤中含兩個(gè)共享的對(duì)象,黑棋子和白棋子,所有棋子的外在屬性都存放在單獨(dú)的容器中。
??
總結(jié)
以上是生活随笔為你收集整理的设计模式C++实现(9)——享元模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。