欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++設(shè)計模式之代理模式

 更新時間:2014年10月08日 10:36:22   投稿:junjie  
這篇文章主要介紹了C++設(shè)計模式之代理模式,本文講解了什么是代理模式、代理模式的使用場合、代理模式的實現(xiàn)代碼等內(nèi)容,需要的朋友可以參考下

前言

青春總是那樣,逝去了才開始回味;大學(xué)生活也是在不經(jīng)意間就溜走了,現(xiàn)在上班的時候,偶爾還會懷念大學(xué)時,大家在一起玩游戲的時光。大學(xué)喜歡玩游戲,但是可悲的校園網(wǎng),速度能把人逼瘋了;還好,后來搞了一個游戲代理,總算能勉勉強強的玩了兩年。時至今日,敲起鍵盤寫設(shè)計模式的時候,又想起了那些美好的時光。好了,這是一篇技術(shù)文章,而不是抒情懷舊的散文;思緒再回到這篇文章上來,游戲代理,是個什么東西,有了它就能讓我們玩游戲的延遲立馬下來了。今天,我并不會去總結(jié)游戲代理是如何實現(xiàn)的,重點是通過游戲代理這個例子來總結(jié)設(shè)計模式中的代理模式。

什么是代理模式?

在GOF的《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對代理模式是這樣說的:為其他對象提供一種代理以控制對這個對象的訪問。結(jié)合上面的游戲代理的例子和下面的圖,我們來進行分析一下。以前你是這樣玩游戲:

現(xiàn)在有了游戲代理,你是這樣玩游戲:

代理服務(wù)器干了什么?它代替你去和游戲服務(wù)器進行交互。它訪問游戲服務(wù)器的速度比你使用校園網(wǎng)訪問游戲服務(wù)器的速度快很多。所以,你的游戲延遲就下來了。

代理模式分為四類:遠(yuǎn)程代理,虛代理,保護代理和智能引用。在下面使用場合會對這四種進行分別介紹。

UML類圖

Proxy

1.保存一個引用使得代理可以訪問實體。若RealSubject和Subject的接口相同,Proxy會引用Subject,就相當(dāng)于在代理類中保存一個Subject指針,該指針會指向RealSubject;
2.提供一個與Subject的接口相同的接口,這樣代理就可以用來替代實體;
3.控制對實體的存取,并可能負(fù)責(zé)創(chuàng)建和刪除它;
4.其它功能依賴于代理的類型,例如:

遠(yuǎn)程代理負(fù)責(zé)對請求及其參數(shù)進行編碼,并向不同地址空間中的實體發(fā)送已編碼的請求;
虛代理可以緩存實體的附加信息,以便延遲對它的訪問;
保護代理檢查調(diào)用者是否具有實現(xiàn)一個請求所必須的訪問權(quán)限。

Subject:定義RealSubject和Proxy的共用接口,這樣就在任何使用RealSubject的地方都可以使用Proxy;

RealSubject:定義Proxy所代理的實體。

使用場合

上面也總結(jié)了,代理模式分為遠(yuǎn)程代理,虛代理,保護代理和智能引用這四種,而分為這四種,就是對應(yīng)不同的使用場合的。

1.遠(yuǎn)程代理為一個對象在不同的地址空間提供局部代理;
2.虛代理根據(jù)需求創(chuàng)建開銷很大的對象;
3.保護代理控制原始對象的訪問;保護代理用于對象應(yīng)該有不同的訪問權(quán)限的時候;
4.智能引用取代了簡單的指針,它在訪問對象時執(zhí)行一些附加操作,它的典型用途包括:

對指向?qū)嶋H對象的引用計數(shù),這樣當(dāng)該對象沒有引用時,可以自動釋放它;
當(dāng)?shù)谝淮我靡粋€持久對象時,將它裝入內(nèi)存;
在訪問一個實際對象前,檢查是否已經(jīng)鎖定了它,以確保其他對象不能改變它。

代碼實現(xiàn)

最簡單的實現(xiàn),對上述UML類圖的直接代碼體現(xiàn):

復(fù)制代碼 代碼如下:

#include <iostream>
using namespace std;
 
#define SAFE_DELETE(p) if (p) { delete p; p = NULL;}
 
class CSubject
{
public:
    CSubject(){};
    virtual ~CSubject(){}
 
    virtual void Request() = 0;
};
 
class CRealSubject : public CSubject
{
public:
    CRealSubject(){}
    ~CRealSubject(){}
 
    void Request()
    {
        cout<<"CRealSubject Request"<<endl;
    }
};
 
class CProxy : public CSubject
{
public:
    CProxy() : m_pRealSubject(NULL){}
    ~CProxy()
    {
        SAFE_DELETE(m_pRealSubject);
    }
 
    void Request()
    {
        if (NULL == m_pRealSubject)
        {
            m_pRealSubject = new CRealSubject();
        }
        cout<<"CProxy Request"<<endl;
        m_pRealSubject->Request();
    }
 
private:
    CRealSubject *m_pRealSubject;
};
 
int main()
{
    CSubject *pSubject = new CProxy();
    pSubject->Request();
    SAFE_DELETE(pSubject);
}

上面的實現(xiàn),就是對代理模式的最原始體現(xiàn),現(xiàn)在提供一個有血有肉的實際應(yīng)用級的體現(xiàn):

復(fù)制代碼 代碼如下:

#include <iostream>
#include <windows.h>
using namespace std;
 
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
 
class KRefCount
{
public:
    KRefCount():m_nCount(0){}
 
public:
    unsigned AddRef(){ return InterlockedIncrement(&m_nCount); }
    unsigned Release(){ return InterlockedDecrement(&m_nCount); }
    void Reset(){ m_nCount = 0; }
 
private:
    unsigned long m_nCount;
};
 
template <typename T>
class SmartPtr
{
public:
    SmartPtr(void)
        : m_pData(NULL)
    {
        m_pReference = new KRefCount();
        m_pReference->AddRef();
    }
 
    SmartPtr(T* pValue)
        : m_pData(pValue)
    {
        m_pReference = new KRefCount();
        m_pReference->AddRef();
    }
 
    SmartPtr(const SmartPtr<T>& sp)
        : m_pData(sp.m_pData)
        , m_pReference(sp.m_pReference)
    {
        m_pReference->AddRef();
    }
 
    ~SmartPtr(void)
    {
        if (m_pReference && m_pReference->Release() == 0)
        {
            SAFE_DELETE(m_pData);
            SAFE_DELETE(m_pReference);
        }
    }
 
    inline T& operator*()
    {
        return *m_pData;
    }
 
    inline T* operator->()
    {
        return m_pData;
    }
 
    SmartPtr<T>& operator=(const SmartPtr<T>& sp)
    {
        if (this != &sp)
        {
            if (m_pReference && m_pReference->Release() == 0)
            {
                SAFE_DELETE(m_pData);
                SAFE_DELETE(m_pReference);
            }
 
            m_pData = sp.m_pData;
            m_pReference = sp.m_pReference;
            m_pReference->AddRef();
        }
 
        return *this;
    }
 
    SmartPtr<T>& operator=(T* pValue)
    {
        if (m_pReference && m_pReference->Release() == 0)
        {
            SAFE_DELETE(m_pData);
            SAFE_DELETE(m_pReference);
        }
 
        m_pData = pValue;
        m_pReference = new KRefCount;
        m_pReference->AddRef();
        return *this;
    }
 
    T* Get()
    {
        T* ptr = NULL;       
        ptr = m_pData;
 
        return ptr;
    }
 
    void Attach(T* pObject)
    {
        if (m_pReference->Release() == 0)
        {
            SAFE_DELETE(m_pData);
            SAFE_DELETE(m_pReference);
        }
 
        m_pData = pObject;
        m_pReference = new KRefCount;
        m_pReference->AddRef();
    }
 
    T* Detach()
    {
        T* ptr = NULL;
 
        if (m_pData)
        {          
            ptr = m_pData;
            m_pData = NULL;
            m_pReference->Reset();
        }
        return ptr;
    }
 
private:
    KRefCount* m_pReference;
    T* m_pData;
};
 
class CTest
{
public:
    CTest(int b) : a(b) {}
private:
    int a;
};
 
int main()
{
    SmartPtr<CTest> pSmartPtr1(new CTest(10));
    SmartPtr<CTest> pSmartPtr2(new CTest(20));
 
    pSmartPtr1 = pSmartPtr2;
}

智能指針使用引用計數(shù)實現(xiàn)時,就是最好的使用代理模式的例子。在上面的例子中,SmartPtr就是一個代理類,而T* m_pData才是實際的數(shù)據(jù)。SmartPtr代理實際的數(shù)據(jù),去實現(xiàn)了指針的行為,添加了引用計數(shù),從而實現(xiàn)了智能指針。

總結(jié)

我在第一次接觸代理模式的時候,看它的UML類圖,發(fā)現(xiàn)它和適配器模式的類適配器很像,再一看,又和裝飾模式非常像;不仔細(xì)區(qū)分,真的是很容易混亂的。下面就做簡單的區(qū)分,說多了也都是“狡辯”了。

1.適配器Adapter為它所適配的對象提供了一個不同的接口。相反,代理提供了與它的實體相同的接口。然而,用于訪問保護的代理可能會拒絕執(zhí)行實體會執(zhí)行的操作,因此,它的接口實際上可能只是實體接口的一個子集。

2.盡管Decorator的實現(xiàn)部分與代理相似,但Decorator的目的不一樣。Decorator為對象添加一個或多個功能,而代理則控制對對象的訪問。

我在這里進行區(qū)分,你們看了,也就像我在咬文嚼字一樣;這就是結(jié)構(gòu)型設(shè)計模式;它們之間都有一些細(xì)微的差別。你也可以說,在適配器模式進行接口適配時,添加一些數(shù)據(jù)轉(zhuǎn)換就變成了遠(yuǎn)程代理;你也可以說裝飾模式雖然功能不一樣,在我看來,大同小異;是的,不管你怎么說,就像1000個讀者心中有1000個哈姆雷特一樣,每個人對設(shè)計模式的理解都是不一樣的;最重要的是我們能在實際應(yīng)用中進行活學(xué)活用,如果能做到這個;不管什么設(shè)計模式,那只是一個名字,就像對于富人來說,錢只是一個銀行卡上的一個數(shù)字一樣。

最后,我堅信分享使我們更加進步,期待大家和我分享你的設(shè)計模式心得。

相關(guān)文章

  • C語言編寫多功能日歷

    C語言編寫多功能日歷

    之前看到本站給大家分享了一則C語言實現(xiàn)的簡單日歷,就手癢了,也想自己寫一個,既然有簡單了,那咱寫個稍微復(fù)雜點的,多功能的吧。呵呵,玩笑玩笑
    2015-03-03
  • C語言實現(xiàn)樹的動態(tài)查找實例代碼

    C語言實現(xiàn)樹的動態(tài)查找實例代碼

    這篇文章主要介紹了C語言實現(xiàn)樹的動態(tài)查找實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C++實現(xiàn)圖書管理系統(tǒng)課程設(shè)計(面向?qū)ο?

    C++實現(xiàn)圖書管理系統(tǒng)課程設(shè)計(面向?qū)ο?

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)圖書管理系統(tǒng)課程設(shè)計,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vscode 配置 C/C++ 編譯環(huán)境的詳細(xì)圖文教程

    vscode 配置 C/C++ 編譯環(huán)境的詳細(xì)圖文教程

    這篇文章主要介紹了vscode 配置 C/C++ 編譯環(huán)境的詳細(xì)教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • C語言實現(xiàn)文件操作實例(簡單圖示講解)

    C語言實現(xiàn)文件操作實例(簡單圖示講解)

    與普通文件載體不同,文件是以硬盤為載體存儲在計算機上的信息集合,文件可以是文本文檔、圖片、程序等等,下面這篇文章主要給大家介紹了關(guān)于C語言實現(xiàn)文件操作實例的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • C語言基礎(chǔ) 原碼、反碼、補碼和移碼詳解

    C語言基礎(chǔ) 原碼、反碼、補碼和移碼詳解

    這篇文章主要介紹了C語言基礎(chǔ) 原碼、反碼、補碼和移碼詳解的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • 教你如何使用qt quick-PathView實現(xiàn)好看的home界面

    教你如何使用qt quick-PathView實現(xiàn)好看的home界面

    pathView的使用類似與ListView,都需要模型(model)和代理(delegate),只不過pathView多了一個路徑(path)屬性,顧名思義路徑就是item滑動的路徑,下面給大家分享qt quick-PathView實現(xiàn)好看的home界面,一起看看吧
    2021-06-06
  • C++ 中時間與時間戳的轉(zhuǎn)換實例詳解

    C++ 中時間與時間戳的轉(zhuǎn)換實例詳解

    這篇文章主要介紹了C++ 中時間與時間戳的轉(zhuǎn)換實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C++基本用法實踐之移動語義詳解

    C++基本用法實踐之移動語義詳解

    移動(move)語義是C++引入了一種新的內(nèi)存優(yōu)化,以避免不必要的拷貝,下面小編就來和大家簡單聊聊C++中移動語義的相關(guān)使用吧,希望對大家有所幫助
    2023-07-07
  • 使用c語言輸出楊輝三角形的簡單方法

    使用c語言輸出楊輝三角形的簡單方法

    這篇文章主要給大家介紹了關(guān)于如何使用c語言輸出楊輝三角形的簡單方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評論