2012-03-12 57 views
3

從這裏:http://www.oodesign.com/proxy-pattern.html代理模式 - 實用性與範例

實用性&實例

的代理設計模式是適用時,有一個需要控制 的對象的訪問,以及當需要對對象進行復雜的引用時。常見的情況,其中 代理模式是適用的是:

虛擬代理:直到需要,在按需創建對象延緩昂貴 對象的創建和初始化(對於 例如,只有當創建RealSubject對象doSomething 方法被調用)。

保護代理:其中一個代理控制訪問RealSubject 方法,通過給訪問一些對象,而拒絕對 他人訪問。

智能參考:提供一複雜的訪問對某些對象 例如跟蹤引用的數目爲一個對象和拒絕 訪問如果達到一定數量時,以及從數據庫加載對象 到存儲器需求。

嘛,不能虛擬代理可以通過一個新的對象創建一個單獨的功能(除了構造函數等)產生的?

不能保護代理是通過簡單地將該函數設爲私有,並讓只有派生類獲得訪問來創建的?或通過朋友課?

不能智能參考文獻是由靜態成員變量創建的,該變量用於統計創建的對象數量?

在哪些情況下Proxy方法應該優先於訪問說明符和繼承?

我錯過了什麼觀點?

回答

3

你的問題有點抽象,我不確定我能否很好地回答,但這裏是我對他們每個人的看法。就我個人而言,我不同意這些東西中的一些是工作最好的設計,但那不是你的問題,而是一個意見問題。

虛擬代理 我不明白你在這裏想說什麼。這裏的模式的要點是,你可能有一個對象A,你知道它需要100MB,並且你不知道你將永遠需要使用這個對象。

爲避免爲該對象分配內存,直到需要時創建一個虛擬對象B,該對象實現與A相同的接口,並且如果調用其任何方法B創建A的實例,從而避免分配內存直到它是必要的。

保護代理 在這裏,我認爲你誤解了模式的使用。這個想法是能夠動態地控制對象的訪問。例如,您可能希望A類能夠訪問B類的方法,除非條件C爲真。正如我相信你可以看到這不能通過使用訪問說明符來實現。

智能退避 在這裏,我想你誤解了智能指針的需求。由於這是一個相當複雜的話題,我只是簡單地提供一個關於它們的問題的鏈接:RAII and smart pointers in C++

如果你從來沒有用自己管理你的記憶的語言編程,那麼這可能會解釋混淆。

我希望這有助於回答您的一些問題。

編輯:

我沒有注意到這個被標記C++,所以我假設你其實認識到需要清理動態內存。單個靜態引用計數僅在您打算只有一個對象實例時纔有效。如果你創建了一個對象的2000個實例,然後刪除了1999個對象,那麼它們都不會釋放它們的內存,直到最後一個對象的範圍顯然不可取爲止(假設你已經跟蹤了所有分配的內存的位置爲了能夠釋放它!)。

編輯2:

假設你有一個類,如下所示:

class A { 
public: 
    static int refcount; 

    int* allocated_memory; 

    A() { 
    ++refcount; 
    allocated_memory = new int[100000000]; 
    } 

    ~A() { 
    if(! --refcount) { 
     delete [] allocated_memory; 
    } 
    } 
} 

和使用它的一些代碼:

int main() { 
    A problem_child; // After this line refcount == 1 
    while(true) { 
    A in_scope;  // Here refcount == 2 

    }     // We leave scope and refcount == 1. 
        // NOTE: in_scope.allocated_memory is not deleted 
        //  and we now have no pointer to it. Leak! 
    return; 
} 

正如你可以在代碼中引用計數看到計算所有引用所有對象,並導致內存泄漏。如果你需要,我可以進一步解釋,但這本身就是一個單獨的問題。

+0

你說過:「*如果你創建了2000個對象實例,然後刪除了1999個對象,那麼它們都不會釋放它們的內存直到最後一個剩下的範圍*」我不明白爲什麼會發生這種情況,請詳細說明。 – 2012-03-13 06:24:59

+0

@AnishaKaul我會在上面的回答中回答 – sji 2012-03-13 10:06:33

+0

@AnishaKaul Done,正如我所說這應該是它自己的問題,我提供的鏈接對問題有很好的解釋。 – sji 2012-03-13 10:20:12

0

代理是一個對象,作爲一個不同的對象來添加一些控制/行爲。智能指針就是一個很好的例子:它像訪問一個原始指針一樣訪問對象,但它也控制着該對象的生命週期。

1

我不是專家,但這裏是我對虛擬代理的想法:如果我們通過控制一個單獨的函數初始化說bool Create();那麼責任和初始化的控制在於類的客戶端。使用虛擬代理,目標是在類中保留創建控制,而客戶端不會意識到這一點。

保護代理:主題被保護的可能有不同類型的客戶端,那些它需要得到所有主題方法未受保護的/無限制的訪問,哪些應該被允許的方法的子集訪問別人因此需要Protection代理。

+0

客戶端只需要「調用」該功能。他不需要做任何事情。 – 2012-03-12 10:36:42

+1

是的,這意味着客戶端知道何時調用Create()。如果客戶不應該知道(因爲它更好地爲客戶服務)何時進行實際創建。 Offcourse,如果客戶的服務更好,那麼明確的Create()會更好。 – fizzbuzz 2012-03-12 10:39:17

0

這是很好的質疑是否有替代標準解決方案的問題。設計模式代表許多人都可以使用的解決方案,其優點是有經驗的編程人員很有可能會識別該模式,從而更容易地維護代碼。但是,所有設計都代表取捨,模式有成本。所以你是正確的挑戰模式的使用和考慮替代方案。

在很多情況下,設計並不僅僅是讓代碼工作,而是考慮它的結構。哪一段代碼「知道」什麼。您提出了一個替代Virtual Prozy動作的方案(就像fizzbuzz所說),從代理到客戶端的創建知識 - 客戶端必須「知道」才能調用Create(),並且知道類的生命週期。而代理人只是將他視爲工作人員的對象,然後當委託人決定它有意義時,就會發生無形的創造。這種對代理人的責任重構被認爲是有價值的,它允許我們在未來改變那些生命週期規則而不改變任何客戶。

保護代理:您的建議要求客戶端具有繼承關係,以便他們可以使用受保護的方法。一般來說,夫妻雙方過於緊密,所以我們引入代理。

智能參考:不,一個靜態計數是不好的。您需要對單個實例的引用進行計數。

如果您仔細研究每個案例,您會發現設計模式有優點。如果你嘗試實現一個替代方案,那麼你可以從一些簡單的設計模式代碼開始,然後發現當你開始重構和改進代碼時,去除重複等等,最終重新設計設計模式 - 這真是一件很棒的事情結果。