目的
替其他物件預留代理者空位,藉此控制存取其他物件。
Provide a surrogate or placeholder for another object to control access to it.
適用
- 遠端代理者(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。
影響結果
實作
代理者未必需要知道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();
}
}
}
}