代理人模式 Proxy Pattern

959 字
5 分鐘
代理人模式 Proxy Pattern

目的#

替其他物件預留代理者空位,藉此控制存取其他物件。

適用#

  • 遠端代理者(remote proxy)用來代理位於不同定址空間的其他物件。虛擬代理者(virtual proxy)會在需要時才建立耗資源的物件,例如ImageProxy。設限代理者(protection proxy)控制原始物件的存取權限,用來對同一物件設定各種不同的存取權限。智慧型指涉者(smart reference)彌補指標的不足,可在存取物件的同時進行額外的動作。

Smart Reference典型的應用: ①累計物件被用幾次,不用時釋放空間。 ②第一次用到時才將永久性物件(persistent object)載入記憶體。 ③在使用前先檢查是否已鎖定完成,確保不會被其他物件更改內容。 參見:http://corrupt003-design-pattern.blogspot.com/2016/10/proxy-pattern.html

結構及成員#

Collaborations: 如果合適(看Proxy的類型而定),Proxy會將訊息轉遞給RealSubject。

  • Proxy: like the ImageProxy持有指向RealSubject物件的reference以便存取真正的物件。如果RealSubject和Subject的介面完全一樣,Proxy也可以直接指向Subject。提供和Subject相同的介面,以便能用在RealSubject所能出現的任何地方。掌控對RealSubject的存取動作,可能還會負責建立及刪除。其他權責要視Proxy種類而定:遠端代理者:負責編碼訊息和參數,再送交給位於不同定址空間的RealSubject。虛擬代理者:可能會快取RealSubject的某些資訊以延緩存取時機(像ImageProxy會快取影像的寬度、高度)。設限代理者:檢查呼叫者是否有存取能力。Subject: like the Graphic制訂RealSubject和Proxy所共同遵循的介面,好讓Proxy可用在RealSubject所能出現的任何地方。RealSubject: like the Image定義Proxy所代表的真正物件。

影響結果#

  • 遠端代理者可隱瞞「物件位於不同定址空間」一事。虛擬代理者可做些最佳化措施,像是需要時才建物件。設限代理者和智慧型指涉者都可在存取物件時做些額外的事。寫入時才拷貝:複製大而複雜的物件是很耗資源的事,如果複製對象的內容沒有被更動過,就不必虛耗資源,用Proxy延遲拷貝程序確保唯有在內容有變時才付出代價。 需加上參用計數功能,此時複製Proxy就只是去遞增計數器內容。當外界更動到Subject內容,Proxy才會真的去拷貝一份並遞減計數器。計數器附為零,就砍Subject。

實作#

代理者未必需要知道RealSubject的確切型別#

  • 如果Proxy類別只透過抽象介面來處理Subject物件,就不用替每一種RealSubject各做一個Proxy類別(Proxy會一視同仁的對待他們)。但如果Proxy會實體化RealSubject(如:虛擬代理者),就必須知道實體類別是誰。

Example: ImageProxy#

// Proxy 實作跟 RealSubject 共同的介面 Icon
public class ImageProxy implements Icon {
// 這是我們的 RealSubject,
// 也就是真正要顯示圖的物件
private ImageIcon mImageIcon;
private URL mUrl;
private Thread mRetrievalThread;
private boolean mRetrieving = false;
// 此範例是從網路上取得圖
public ImageProxy(URL url)
{
mUrl = url;
}
@Override
public int getIconWidth()
{
// 在圖下載完成前, 先傳回預設的值
if(mImageIcon != null)
{
return mImageIcon.getIconWidth();
}
else
{
return 0;
}
}
@Override
public int getIconHeight()
{
// 在圖下載完成前, 先傳回預設的值
if(mImageIcon != null)
{
return mImageIcon.getIconHeight();
}
else
{
return 0;
}
}
@Override
public int paintIcon(...)
{
// 圖下載好了, 畫圖的事就轉給
// RealSubject 做
if(mImageIcon != null)
{
mImageIcon.paintIcon(...);
}
else
{
// 第一次下載圖
drawString("Loading icon, please wait...");
if(!mRetrieving)
{
mRetrieving = true;
mRetrievalThread = new Thread(new Runnable() {
@Override
public void run()
{
mImageIcon = new ImageIcon(mUrl, "icon");
}
});
mRetrievalThread.start();
}
}
}
}

文章分享

如果這篇文章對你有幫助,歡迎分享給更多人!

代理人模式 Proxy Pattern
https://linziyou.info/posts/2020-11-23-代理人模式-proxy-pattern/
作者
Lin Ziyou
發布於
2020-11-23
許可協議
CC BY-NC-SA 4.0
最後更新於 2020-11-23,距今已過 1925 天

部分內容可能已過時

Profile Image of the Author
Lin Ziyou
Hi! I'm Jerry~
分類
標籤
站點統計
文章
45
分類
8
標籤
10
總字數
43,470
運作天數
0
最後活動
0 天前

目錄