日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 編程 > C++ > 正文

C++設計模式之享元模式

2020-05-23 14:20:41
字體:
來源:轉載
供稿:網友

前言

無聊的時候,也去QQ游戲大廳玩五子棋或者象棋;作為程序員,看到一個產品,總要去想想它是怎么設計的,怎么完成的,我想這個是所有程序員都會做的事情吧(強迫癥???)。有的時候,想完了,還要做一個DEMO出來,才能體現自己的NB,然后還有點小成就感。

在玩五子棋或象棋的時候,我就想過,騰訊那幫伙計是怎么做的呢?五子棋的棋子有黑白兩色,難道每次放一個棋子就new一個對象么?象棋有車、馬、相、士、帥、炮和兵,是不是每盤棋都要把所有的棋子都new出來呢?如果真的是每一個棋子都new一個,那么再加上那么多人玩;那要new多少對象啊,如果是這樣做的話,我想有多少服務器都是搞不定的,可能QQ游戲大廳會比12306還糟糕。那騰訊那幫伙計是如何實現的呢?那就要說到今天總結的享元模式了。

什么是享元模式?

在GOF的《設計模式:可復用面向對象軟件的基礎》一書中對享元模式是這樣說的:運用共享技術有效地支持大量細粒度的對象。

就如上面說的棋子,如果每個棋子都new一個對象,就會存在大量細粒度的棋子對象,這對服務器的內存空間是一種考驗,也是一種浪費。我們都知道,比如我在2013號房間和別人下五子棋,2014號房間也有人在下五子棋,并不會因為我在2013號房間,而別人在2014號房間,而導致我們的棋子是不一樣的。這就是說,2013號房間和2014號房間的棋子都是一樣的,所有的五子棋房間的棋子都是一樣的。唯一的不同是每個棋子在不同的房間的不同棋盤的不同位置上。所以,對于棋子來說,我們不用放一個棋子就new一個棋子對象,只需要在需要的時候,去請求獲得對應的棋子對象,如果沒有,就new一個棋子對象;如果有了,就直接返回棋子對象。這里以五子棋為例子,進行分析,當玩家在棋盤上放入第一個白色棋子時,此時由于沒有白色棋子,所以就new一個白色棋子;當另一個玩家放入第一個黑色棋子時,此時由于沒有黑色棋子,所以就需要new一個黑色棋子;當玩家再次放入一個白色棋子時,就去查詢是否有已經存在的白色棋子對象,由于第一次已經new了一個白色棋子對象,所以,現在不會再次new一個白色棋子對象,而是返回以前new的白色棋子對象;對于黑色棋子,亦是同理;獲得了棋子對象,我們只需要設置棋子的不同棋盤位置即可。

UML類圖

C++設計模式之享元模式

Flyweight:描述一個接口,通過這個接口flyweight可以接受并作用于外部狀態;

ConcreteFlyweight:實現Flyweight接口,并為定義了一些內部狀態,ConcreteFlyweight對象必須是可共享的;同時,它所存儲的狀態必須是內部的;即,它必須獨立于ConcreteFlyweight對象的場景;

UnsharedConcreteFlyweight:并非所有的Flyweight子類都需要被共享。Flyweight接口使共享成為可能,但它并不強制共享。

FlyweightFactory:創建并管理flyweight對象。它需要確保合理地共享flyweight;當用戶請求一個flyweight時,FlyweightFactory對象提供一個已創建的實例,如果請求的實例不存在的情況下,就新創建一個實例;

Client:維持一個對flyweight的引用;同時,它需要計算或存儲flyweight的外部狀態。

實現要點

根據我們的經驗,當要將一個對象進行共享時,就需要考慮到對象的狀態問題了;不同的客戶端獲得共享的對象之后,可能會修改共享對象的某些狀態;大家都修改了共享對象的狀態,那么就會出現對象狀態的紊亂。對于享元模式,在實現時一定要考慮到共享對象的狀態問題。那么享元模式是如何實現的呢?

在享元模式中,有兩個非常重要的概念:內部狀態和外部狀態。

內部狀態存儲于flyweight中,它包含了獨立于flyweight場景的信息,這些信息使得flyweight可以被共享。而外部狀態取決于flyweight場景,并根據場景而變化,因此不可共享。用戶對象負責在必要的時候將外部狀態傳遞給flyweight。

flyweight執行時所需的狀態必定是內部的或外部的。內部狀態存儲于ConcreteFlyweight對象之中;而外部對象則由Client對象存儲或計算。當用戶調用flyweight對象的操作時,將該狀態傳遞給它。同時,用戶不應該直接對ConcreteFlyweight類進行實例化,而只能從FlyweightFactory對象得到ConcreteFlyweight對象,這可以保證對它們適當地進行共享;由于共享一個實例,所以在創建這個實例時,就可以考慮使用單例模式來進行實現。

享元模式的工廠類維護了一個實例列表,這個列表中保存了所有的共享實例;當用戶從享元模式的工廠類請求共享對象時,首先查詢這個實例表,如果不存在對應實例,則創建一個;如果存在,則直接返回對應的實例。

代碼實現:

 

復制代碼代碼如下:

#include <iostream>
#include <map>
#include <vector>
using namespace std;
 
typedef struct pointTag
{
    int x;
    int y;
 
    pointTag(){}
    pointTag(int a, int b)
    {
        x = a;
        y = b;
    }
 
     bool operator <(const pointTag& other) const
     {
         if (x < other.x)
         {
             return true;
         }
         else if (x == other.x)
         {
             return y < other.y;
         }
 
         return false;
     }
}POINT;
 
typedef enum PieceColorTag
{
    BLACK,
    WHITE
}PIECECOLOR;
 
class CPiece
{
public:
    CPiece(PIECECOLOR color) : m_color(color){}
    PIECECOLOR GetColor() { return m_color; }
 
    // Set the external state
    void SetPoint(POINT point) { m_point = point; }
    POINT GetPoint() { return m_point; }
 
protected:
    // Internal state
    PIECECOLOR m_color;
 
    // external state
    POINT m_point;
};
 
class CGomoku : public CPiece
{
public:
    CGomoku(PIECECOLOR color) : CPiece(color){}
};
 
class CPieceFactory
{
public:
    CPiece *GetPiece(PIECECOLOR color)
    {
        CPiece *pPiece = NULL;
        if (m_vecPiece.empty())
        {
            pPiece = new CGomoku(color);
            m_vecPiece.push_back(pPiece);
        }
        else
        {
            bool bFound = false; // 非常感謝fireace指出的問題
            for (vector<CPiece *>::iterator it = m_vecPiece.begin(); it != m_vecPiece.end(); ++it)
            {
                if ((*it)->GetColor() == color)
                {
                    bFound = true;
                    pPiece = *it;
                    break;
                }
                bFound = false;
            }
            if (!bFound)
            {
                pPiece = new CGomoku(color);
                m_vecPiece.push_back(pPiece);
            }
        }
        return pPiece;
    }
 
    ~CPieceFactory()
    {
        for (vector<CPiece *>::iterator it = m_vecPiece.begin(); it != m_vecPiece.end(); ++it)
        {
            if (*it != NULL)
            {
                delete *it;
                *it = NULL;
            }
        }
    }
 
private:
    vector<CPiece *> m_vecPiece;
};
 
class CChessboard
{
public:
    void Draw(CPiece *piece)
    {
        if (piece->GetColor())
        {
            cout<<"Draw a White"<<" at ("<<piece->GetPoint().x<<","<<piece->GetPoint().y<<")"<<endl;
        }
        else
        {
            cout<<"Draw a Black"<<" at ("<<piece->GetPoint().x<<","<<piece->GetPoint().y<<")"<<endl;
        }
        m_mapPieces.insert(pair<POINT, CPiece *>(piece->GetPoint(), piece));
    }
 
    void ShowAllPieces()
    {
        for (map<POINT, CPiece *>::iterator it = m_mapPieces.begin(); it != m_mapPieces.end(); ++it)
        {
            if (it->second->GetColor())
            {
                cout<<"("<<it->first.x<<","<<it->first.y<<") has a White chese."<<endl;
            }
            else
            {
                cout<<"("<<it->first.x<<","<<it->first.y<<") has a Black chese."<<endl;
            }
        }
    }
 
private:
    map<POINT, CPiece *> m_mapPieces;
};
 
int main()
{
    CPieceFactory *pPieceFactory = new CPieceFactory();
    CChessboard *pCheseboard = new CChessboard();
 
    // The player1 get a white piece from the pieces bowl
    CPiece *pPiece = pPieceFactory->GetPiece(WHITE);
    pPiece->SetPoint(POINT(2, 3));
    pCheseboard->Draw(pPiece);
 
    // The player2 get a black piece from the pieces bowl
    pPiece = pPieceFactory->GetPiece(BLACK);
    pPiece->SetPoint(POINT(4, 5));
    pCheseboard->Draw(pPiece);
 
    // The player1 get a white piece from the pieces bowl
    pPiece = pPieceFactory->GetPiece(WHITE);
    pPiece->SetPoint(POINT(2, 4));
    pCheseboard->Draw(pPiece);
 
    // The player2 get a black piece from the pieces bowl
    pPiece = pPieceFactory->GetPiece(BLACK);
    pPiece->SetPoint(POINT(3, 5));
    pCheseboard->Draw(pPiece);
 
    /*......*/
 
    //Show all cheses
    cout<<"Show all cheses"<<endl;
    pCheseboard->ShowAllPieces();
 
    if (pCheseboard != NULL)
    {
        delete pCheseboard;
        pCheseboard = NULL;
    }
    if (pPieceFactory != NULL)
    {
        delete pPieceFactory;
        pPieceFactory = NULL;
    }
}

 

內部狀態包括棋子的顏色,外部狀態包括棋子在棋盤上的位置。最終,我們省去了多個實例對象存儲棋子顏色的空間,從而達到了空間的節約。

在上面的代碼中,我建立了一個CCheseboard用于表示棋盤,棋盤類中保存了放置的黑色棋子和白色棋子;這就相當于在外部保存了共享對象的外部狀態;對于棋盤對象,我們是不是又可以使用享元模式呢?再設計一個棋局類進行管理棋盤上的棋子布局,用來保存外部狀態。對于這個,這里不進行討論了。

優點

享元模式可以避免大量非常相似對象的開銷。在程序設計時,有時需要生成大量細粒度的類實例來表示數據。如果能發現這些實例數據除了幾個參數外基本都是相同的,使用享元模式就可以大幅度地減少對象的數量。

使用場合

Flyweight模式的有效性很大程度上取決于如何使用它以及在何處使用它。當以下條件滿足時,我們就可以使用享元模式了。

1.一個應用程序使用了大量的對象;
2.完全由于使用大量的對象,造成很大的存儲開銷;
3.對象的大多數狀態都可變為外部狀態;
4.如果刪除對象的外部狀態,那么可以用相對較少的共享對象取代很多組對象。

擴展

之前總結了組合模式組合模式,現在回過頭來看看,享元模式就好比在組合模式的基礎上加上了一個工廠類,進行共享控制。是的,組合模式有的時候會產生很多細粒度的對象,很多時候,我們會將享元模式和組合模式進行結合使用。

總結

使用享元模式可以避免大量相似對象的開銷,減小了空間消耗;而空間的消耗是由以下幾個因素決定的:

1.實例對象減少的數目;
2.對象內部狀態的數目;對象內部狀態越多,消耗的空間也會越少;
3.外部狀態是計算的還是存儲的;由于外部狀態可能需要存儲,如果外部狀態存儲起來,那么空間的節省就不會太多。

共享的Flyweight越多,存儲節約也就越多,節約量隨著共享狀態的增多而增大。當對象使用大量的內部及外部狀態,并且外部狀態是計算出來的而非存儲的時候,節約量將達到最大。所以,可以使用兩種方法來節約存儲:用共享減少內部狀態的消耗;用計算時間換取對外部狀態的存儲。

同時,在實現的時候,一定要控制好外部狀態與共享對象的對應關系,比如我在代碼實現部分,在CCheseboard類中使用了一個map進行彼此之間的映射,這個映射在實際開發中需要考慮的。

好了,享元模式就總結到這里了。希望大家和我分享你對設計模式的理解。我堅信:分享使我們更進步。
PS:至于騰訊那幫伙計到底是如何實現QQ游戲大廳的,我也不知道,這里也完全是猜測的,請不要以此為基準。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
国产久卡久卡久卡久卡视频精品| 伊人中文字幕在线观看| 中文字幕欧美日韩va免费视频| 日韩一级二级三级| 精品欧美久久久| 精产国产伦理一二三区| 久久91精品久久久久久秒播| 天堂精品高清1区2区3区| 欧美三级日韩在线| 欧美日韩国产综合久久| 久久久久黄色| 欧美二三四区| 日韩欧美一级精品久久| 国产劲爆久久| 亚洲欧美日本另类| 日韩精品在线观看视频| 91精品国产91久久久久久三级| 欧美日韩国产不卡在线看| 亚洲大片精品永久免费| 午夜精品一区二区三区视频免费看| 欧美日韩在线观看首页| 亚洲国产福利| 在线视频你懂得一区| 欧美日韩中文| 国产婷婷一区二区| 天堂在线www天堂中文在线| 国产欧美日韩综合精品| 国产午夜在线观看| 日韩午夜一区| 国产欧美综合在线| 天天摸日日摸狠狠添| 国产在线欧美| 亚洲欧美999| 日韩在线 中文字幕| 精品国产免费观看一区| 亚洲一级二级| 在线精品日韩| 一级片在线免费看| 欧美日韩综合在线免费观看| 久艹在线视频| 精品日韩在线播放| 在线视频国内一区二区| 免费看黄资源大全高清| 精品网站999www| 午夜福利一区二区三区| 福利一区二区| 国产激情三区| 黄色一级大片在线免费看国产一| 久久精品卡一| www中文字幕在线观看| 欧美日韩国产123区| 亚洲三级网站| 日韩网站中文字幕| 在线中文字幕视频| 成人xxxx| 国产蜜臀在线| 欧美在线视频第一页| 精品日韩99亚洲| 国产永久在线观看| 最近中文av字幕在线中文| 久久永久免费视频| 中文字幕 欧美日韩| 一区二区精品免费| 免费精品国产自产拍在| 中文字幕 欧美日韩| 精品激情国产视频| 日本国产在线视频| 午夜国产福利一区二区| 在线观看国产一级片| 日韩三级视频在线| 国产字幕在线看| 欧美日韩在线观看首页| 影音先锋一区二区资源站 | 综合激情一区| 国产亚洲欧美色| 欧美日韩精品区| 蜜桃久久av一区| 午夜伊人狠狠久久| 91麻豆精品在线| 亚洲成av人片一区二区密柚| 深夜福利亚洲| www.日韩免费| 亚洲高清在线免费| 亚洲制服一区| 国产不卡在线观看视频| 日韩欧美国产午夜精品| 人人做人人澡人人爽欧美| wwwwww在线观看| 亚洲久草视频| 精品视频资源站| 国产资源中文字幕| 久久夜色精品国产欧美乱极品| 欧美日韩不卡在线视频| 国产香蕉免费精品视频| 欧美高清一级片在线| 国产无套粉嫩白浆在线2022年| 亚洲国产欧美久久| 免费国产h视频在线观看86| 日韩免费看网站| 中文在线第一页| 欧美一级欧美三级在线观看| 在线亚洲人成| 精品亚洲永久免费| 欧美国产一区视频在线观看| 国产在线高潮| 精品人妻一区二区免费视频| 中文字幕视频在线免费欧美日韩综合在线看| 精品免费久久久| 日韩视频精品在线| 中文字幕久精品免费视频| 日韩欧美成人一区二区三区| 欧美日韩成人综合| 一区精品在线播放| 色综合婷婷久久| 久久精品免费在线观看| 欧美日韩国产一级片| 日韩久久不卡| 国产福利久久久| 日韩亚洲欧美中文字幕| 欧洲精品久久久| 国产欧美中文字幕| 一区二区精品免费| 国产欧美日韩第一页| 亚洲免费在线观看av| 中文字幕在线观看播放| 中文字幕在线观看网址| 国产激情99| 蜜桃久久av一区| 精品久久久久久无| 亚洲最新免费视频| 中文字幕国产视频| 欧美日韩在线播放一区| 日韩欧美在线视频| 欧美日韩亚洲91| 91久久精品国产91性色69| 亚洲国产综合久久| 色综合影院在线| 91精品在线国产| 亚洲三级中文字幕| 欧美sm一区| 亚洲高清中文字幕| 国产高潮久久久| 国产91一区| 精品国产999| 亚洲小说春色综合另类网蜜桃| 视频一区视频二区中文| 天天综合日日夜夜精品| 国产福利久久久| 日韩久久99| 日韩.欧美.亚洲| 日韩欧美在线综合网| 亚洲一区在线观看网站| 久久精品久久精品亚洲人| av丝袜在线| 在线观看91精品国产入口| 天天综合天天添夜夜添狠狠添| 日韩精品福利一区二区三区| 欧美日韩精品是欧美日韩精品| 欧美日韩综合在线观看| 久久69成人| 不卡在线视频| 亚洲高清视频一区| 日韩三级精品电影久久久| 国产欧美第一页| 国产一区久久久| 精品在线网站观看| 亚洲视频色图| 国产91久久久久蜜臀青青天草二| 中文网丁香综合网| 日韩亚洲欧美中文三级| 国产成人精品三级| 精品一二三四| 国产在线中文字幕| 午夜黄色小视频| 日韩精品在线中文字幕| 日韩中文在线中文网三级| 日本黄色一区二区| 日韩欧美一卡二卡| 亚洲一区在线观看免费| 日韩欧美中文免费| 欧美日韩精品欧美日韩精品一| 日韩精品视频在线免费观看| 精品一区二区三区中文字幕在线| 日韩久久99| 欧美日韩国产一中文字不卡| 国产三级精品在线观看| 中文字幕久久av| 婷婷综合福利| 欧美一级欧美三级在线观看| 91精品国产综合久久蜜臀| 久久麻豆视频| 亚洲乱码中文字幕综合| 久久99久久久欧美国产| 欧美日韩国产123区| 亚洲国产无线乱码在线观看| av丝袜在线| 日韩中文字幕在线视频播放| www.三级.com| 久久久久黄色| 欧美日韩亚洲第一| 亚洲女同中文字幕| 亚洲国产一区自拍| 91精品视频国产| 国产色综合网| 一区二区不卡在线| 精品亚洲综合| 欧美自拍一区| 91精品婷婷国产综合久久竹菊| 免费高清特黄a大片| 日本精品免费观看高清观看| 欧美日韩乱国产| 国产美女主播视频一区| 国产一级在线免费观看| 精品在线一区二区| 日本xxxwww免费视频| 一区二区三区四区五区视频在线观看 | 欧美日韩视频免费看| 日韩在线视频观看| 欧美不卡一区二区| 国产在线欧美| 中文字幕在线观看欧美| 欧美日韩国产大片| 久久久久久99精品| 欧美黄页在线免费观看| 本道综合精品| 91欧美日韩| 国产区在线看| 国产手机精品视频| 精品国产31久久久久久| 日韩视频在线一区二区| 久久人人88| 国产男女av| 国产欧美日韩第一页| 99在线精品视频免费观看20| 一区二区不卡视频| 欧美日韩国产一二三| 国产亚洲人成a一在线v站| 亚洲永久字幕| 美国av一区二区| 欧美大片在线观看一区| 亚洲精华国产欧美| 中文在线不卡| 国产成人日日夜夜| 国产午夜精品视频| 欧美久久在线| 久久香蕉av| 日韩国产专区| 亚洲一区二区三区精品中文字幕| 国产三级视频网站| 日韩亚洲不卡在线| 日韩高清在线一区二区| 中文在线第一页| 欧美乱大交xxxxx免费| 国产免费播放一区二区| 国产欧美日韩在线看| 91精品国产综合久久精品| 在线不卡日本| 国内激情久久| 国产欧美日韩在线看| 欧美三级一区二区三区| 视频一区中文字幕国产| 亚洲高清在线观看一区| 欧美高清一区| 91 中文字幕| 中文字幕久精品免费视频| 日韩字幕在线观看| 狠狠色噜噜狠狠狠狠97| 成人无遮挡免费网站视频在线观看| 精品欧美不卡一区二区在线观看| 激情综合色综合久久| 亚洲国产午夜精品| 国产丝袜欧美中文另类| 中文字幕在线中文字幕二区| 一区二区三区在线不卡| 日韩中文字幕观看| 国产网站欧美日韩免费精品在线观看 | www.中文字幕在线观看| 日韩欧美亚洲国产一区| 最近中文av字幕在线中文| 91精品国产入口| 日韩欧美在线第一页| 中文字幕亚洲免费| 国产高清精品在线观看| 日本精品专区| 国产永久在线观看| 日本黄色一区二区三区| 国产福利一区二区| 三级精品视频| 在线国产1区| 日本xxxwww免费视频| 天天综合天天添夜夜添狠狠添| 亚洲成av人片在线| 欧美激情视频一区二区三区在线播放 | 欧美亚洲视频在线看网址| 精品国产网站在线观看| 中文精品在线| 九一久久久久久| 激情综合色综合久久| 欧美激情一区二区三区在线| 欧美日韩国产首页在线观看| 丰满少妇一区| 91精品国产91久久久久青草| 一本一道久久a久久精品综合蜜臀| 欧美亚洲专区| 欧美日韩在线视频首页| 韩国一区二区av| 不卡在线视频| 视频一区二区中文字幕| 中文国产字幕在线观看| 国产视频一区三区| 欧美日韩亚州综合| 一区二区不卡在线| 日韩在线三区| 亚洲视频色图| 中文字幕亚洲一区在线观看| 国产亚洲短视频| 国产三级精品网站| 最新中文字幕在线播放| 日韩免费视频一区| 欧美国产亚洲一区| 亚洲一级在线| 日韩视频在线免费看| 国产黄在线播放| 日韩欧美亚洲国产一区| 国产成人中文字幕| 91久久久精品国产| 91精品国产综合久久久久久漫画 | 欧美三级三级三级爽爽爽| 国产三级精品网站| 日韩国产欧美三级| 日韩精品视频在线观看视频| 日本精品福利视频| 国产视频1区| 日韩欧美国产高清91| 日韩中文首页| 国产免费不卡av| 午夜精品一区二区三区免费视频| 中文字幕在线视频网| 欧美日韩国产首页| 精品视频www| 欧美日韩国产免费观看| 精品亚洲永久免费| 欧美久久一二三四区| 日韩视频在线一区二区三区| 欧美在线亚洲一区| 在线不卡一区二区| 精品欧美久久久| 三级精品视频| 成人久久久久| 国产视频一二区| 在线一区二区不卡| 欧美三级一区二区三区| 久久久水蜜桃| www.狠狠干| 中文字幕一区二区三区精品| 国产在线观看精品| 日韩三级视频在线| √新版天堂资源在线资源| 伊人永久在线| 精品一区二区三区中文字幕在线| 亚洲第一视频| 日韩免费电影网站| 在线视频你懂得一区| 日韩欧美综合在线视频| 欧美日韩激情一区| 欧美久久在线| 国产在线观看黄色| 92久久精品| 亚洲欧美视频一区二区三区| 久久精品99国产国产精| 欧美日韩中文字幕综合视频| 91精品国产91久久久久| 黄色一区二区视频| 欧美高清一区| 91精品蜜臀在线一区尤物| 中文天堂资源在线| 日韩精品在线视频| 色99中文字幕| av一区二区高清| 欧美日韩中文另类| 免费日韩精品中文字幕视频在线| 日韩精品在线视频| 天天综合天天综合| 久久久精品日韩欧美| 成人xxxx| 91久久久精品| 欧美日韩亚洲一区| 国产日韩av高清| 精品欧美久久久| 黄色国产网站在线观看| 欧美国产一区视频在线观看| 国产三级做爰在线观看| 欧美三级在线看| 国产乱码午夜在线视频| 亚洲高清不卡一区| 亚洲乱码一区av黑人高潮| 国产免费永久在线观看| 91av久久久| 人人做人人澡人人爽欧美| 中文字幕在线日韩|