Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 代理模式與Android

代理模式與Android

編輯:關於Android編程

代理模式(Proxy)


一、 什麼是代理模式

先來看看官方的說法,代理模式就是為其他對象提供一種代理,以控制對這個對象的訪問。

看來這個官方的說法的確有點官方,看了還是讓人感覺不點不知所措,還是不明白代理模式是什麼,究竟是用來做什麼的。

其實代理這個名詞,對於我們來說其實並不陌生,生活中有很多關於代理的例子。例如校園代理等,就以校園代理來講,這個校園代理就是為他對應的上司的作代理,而這個校園代理的工作就是訪問校園中的學生,例如對學生進行問卷之類的事。在這個例子中,學生就是官方說法中的其他對象,校園代理的上司就通過控制這個校園代理來控制對學生的訪問。這下應該明白一點了吧。


二、 代理模式的類圖

\


三、 代理模式的實現代碼(C++實現)<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD48cD7S1MnPw+bLtbXE0KPUsLT6wO3OqsD919OjrM7Sw8fAtNK7tsO0+sDtxKPKvbXEt+eyyaOszqrBy7j8usO12MDtveLV4rj2xKPKvaOsu7nKx9Kq1/fSu7XjtcS94srNtcSho9Taz8LD5rXEtPrC69bQo6y9q7P2z9bI/bj2wOCjrFdvcmtlcqGiQm9zc7rNU2Nob29sUHJveHmjrMv7w8e31rHwttTTpsnPzby1xFN1YmplY3SholJlYWxTdWJqZWN0us1Qcm94edXiyP249sDgo6y2+NXi0KnA4NbQtcRkb1N1cnZlebe9t6ijrL7NysfP4LWx09rJz8281tC1xFJlcXVlc3S3vbeooaM8L3A+PHA+IDwvcD48cD7XoqO6xuTKtcnPzbzWu8rH0ru49rT6wO3Eo8q9tcRVTUzEo9DNzbyjrFJlcXVlc3TG5Mq1yse0+rHt18XL+dPQUHJveHm6zVJlYWxTdWJqZWN0tcS5stPDvdO/2qOstviyu732vfbKx9XiwO/L+dC0tcTSu7j2oaM8L3A+PHA+IDwvcD48cD7G5Mq1z9a0+sLryOfPwqOocHJveHkuY3Bwo6mjujwvcD48cD4xoaJXb3JrZXLA4LXEtqjS5cjnz8KjrMv809DSu7j2ZG9TdXJ2ZXm1xL3Tv9o8L3A+PHA+PC9wPjxwcmUgY2xhc3M9"brush:java;">class Worker { public: virtual void doSurvey() = 0; virtual ~Worker(){} };

2、Boss類定義如下,它繼承Worker類,並實現doSurvey接口

class Boss : public Worker
{
public:
     virtual void doSurvey()
     {
        cout << "The ABCDE company do sruvey!" << endl;
     }
};

3、SchoolProxy類定義如下,它同樣繼承Worker類,並實現doSurvey接口,該類維護一個Boss類的對象的引用,並在它的中doSurvey方法中調用Boss的doSurvey方法。

class SchoolProxy : public Worker
{
public:
     SchoolProxy():
        _boss(NULL)
     {
     }
     virtual ~SchoolProxy()
     {
        if(_boss != NULL)
        {
            delete _boss;
        }
     }
     SchoolProxy(const SchoolProxy&proxy)
     {
        _boss = newBoss(*proxy._boss);
     }
     SchoolProxy& operator=(const SchoolProxy &rhs)
     {
        if(this != &rhs)
        {
            SchoolProxytmp_proxy(rhs);
            Boss *tmp_boss =tmp_proxy._boss;
            tmp_proxy._boss = _boss;
            _boss = tmp_boss;
        }
        return *this;
     }
     virtual void doSurvey()
     {
        if(_boss == NULL)
        {
            _boss = new Boss();
        }
        _boss->doSurvey();
     }
private:
     Boss *_boss;
};

注:此類中的Boss也可不使用指針,而直接使用對象。但是因為java或C#這類的語言並不支持棧上對象,所有的對象都是new出來的,所以這樣的寫法與java和C#更相似。

4、調用方法如下:

int main()
{
	SchoolProxy *proxy = new SchoolProxy();
	proxy->doSurvey();
	delete proxy;
	return 0;
}
從上面的代碼,我們可以清晰地看到,校園代理SchoolProxy是如何幫助它的Boss來完成做調查的工作的。

四、 代理模式的應用

看了上面的代碼,我想代理模式的操作和原理,大家都差不多可以理解了,但是其實代理還是有不只一種的,根據通常的使用,可以分為四類。

1) 遠程代理

它為一個對象在不同的地址空間提供局部代表。這樣就可以隱藏一個對象存在於不同地址空間的事實,它的例子就是WebServer。

2) 虛擬代理

它根據需求創建開銷比較大的對象,通過它來存放實例化需要很長時間的真實對象。例如,當我們浏覽網頁時,網頁中可能有一些比較大的圖片,雖然圖片比較大,但是你還是可以很快地打開網頁,然而圖片卻不能在第一時間顯示,可能要在幾秒後才能正常顯示,在這裡就是通過虛擬代理來替換真實的圖片。

3) 保護代理

它用於控制對原對象的訪問,保護代理用於對象應該有不同的訪問權限的時候。

4) 智能引用

它用於指當調用真實對象時,代理執行額外的一些操作,處理另外一些事情。例如C++中的智能指針,它取代了簡單的指針,它會對它所指向的對象執行一些額外的操作。

五、 代理模式的真實應用之share_ptr

看了上面的代碼,看了上面的解說,你可能覺得代理模式沒什麼作用,那麼你就錯了,下面來看看,上面四種代理模式其中一種智能引用的強大用處。

有使用過C++的程序員,肯定知道智能指針這個好東西,它可以讓大大減少我們對內存的管理難度,因為它通過以對象管理資源的方法,使指針指向向的堆內存像棧內存一樣,可以自動釋放。

下面就以本人實現的share_ptr來說明智能引用的代理模式的應用,首先來看看類的定義:

template 
class SharePtr
{
    public:
        SharePtr(T *tptr = NULL);
        SharePtr(const SharePtr &sptr);
        SharePtr& operator=(const SharePtr &sptr);
        SharePtr& operator=(T *tptr);
        ~SharePtr();
        T&operator*()const;
        T*operator->()const;
        bool operator==(const SharePtr &sptr)const;
        bool operator!=(const SharePtr &sptr)const;
        bool operator==(const T *tptr)const;
        bool operator!=(const T *tptr)const;
        const T* getPtr()const;
   private://function
        void _decUsed();
        inline void _nullTest()const;
        inline bool _isSame(const SharePtr &sptr)const;
        inline bool _isSame(const T *tptr)const;
   private://data
        T *_ptr;
        size_t *_used;//引用計數,為0時釋放ptr指向的對象
};

它的定義就只有這麼多了,看了上面的定義,你可以會產生疑問,這個真的應用了上面所說的代理模式嗎?上面的代理模式不是要有一個Subject類、一個RealSubject類和一個Proxy類的嗎?而RealSubject類和Proxy是Subject的子類,需要定義Subject的接口的嗎?為什麼這裡只有一個類呢?

現在你看不出來,我並不怪你。看下去自然會明白。

智能指針,這裡以share_ptr為例,它的目的就是通過一個類來模仿一個指針的行為,並提供指針沒有的功能,就是當指針變量出了作用域後,自動處理指針指向的內存的功能。所以上面你看到的SharePtr模板類,就相當於Proxy類。

那RealSubject類呢?因為智能指針是指針的代理,那麼RealSubject類當然就是SharePtr中的成員變量T,我覺得說是T類型的指針T*更加恰當。哈哈,奇妙吧!

那麼Subject類呢?這裡是什麼充當這個類呢?從代理模式的類圖可以看到Subject類定義的是RealSubject和Proxy的共有接口,你想想看,既然RealSubject是一個指針,那麼它的操作就是*、->、==、!=和 = 這五種了,由於這些操作本來就是原生的操作,並不是什麼特別的規定,所以在這裡並沒有這個Subject,但是可以看到,這些共有的接口或者說是操作,上面的SharePtr類中,還是有實現的。

換一個角度來說,*、->、==、!=和 =這五類操作就是Subject類中的接口,但是在這裡並沒有必要實現一個Subject的基類,然後讓SharePtr來繼承它。因為指針並不需要繼承Subject就已經具有這五類操作了。所以這裡把這個類省去了。

這下你應該明白,為什麼這裡的一個類就是一個代理模式了吧。其實我覺得學習設計模式最重要的還是學習它的思想,學習的解決問題的方法以及如何用它架構我們的程序,而不是對照著類圖或者它的定義來生搬硬套。上面的智能指針就是一個例子。

其實智能指針並不是一個指針變量,它只是一個定義在棧上的對象,通過運算符重載使其行為像一個指針變量。當程序運行出了其作用域後,就會析構銷毀,執行相應的操作。下面再來簡單看看,這個代理為我們做了一些什麼額外的事情。

例如,當對象釋放時,會進行如下操作:

template 
SharePtr::~SharePtr()
{
    _decUsed();
}
template 
void SharePtr::_decUsed()
{
    --*_used;
    if(*_used ==0)
    {
        if(_ptr!= NULL)
        {
            delete _ptr;
            _ptr= NULL;
        }
        delete _used;
        _used = NULL;
    }
}

更多的實現和額外操作,可查看源代碼。

六、 Android中的代理模式

在Android中代理模式也是使用廣泛的,例如ActivityManagerProxy類就是一個代理,它是ActivityManagerNative的代理,也就是說ActivityManagerProxy是上面所說的Proxy類,而ActivityManagerNative就相當於RealSubject類,它們都有一個共有的接口IActivityManager。


在這裡還有一個重要的類:ActivityManager,它相當於代理模式的類圖中的client。在這個類中,可以看到大量的getxxx函數,這些函數,都會調用到ActivityManagerNative類的getDefault()方法,而該方法會獲得一個共用的單例的IActivityManager引用,然後通過多態來調用代理中的實現。


注:由於時間的關系,沒有深入去研究。


七、 代碼地址

http://download.csdn.net/detail/ljianhui/7468509

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved