热门问题
时间线
聊天
视角
代理模式
来自维基百科,自由的百科全书
Remove ads
代理模式(英語:proxy pattern),是程式設計中的一種設計模式。所謂的代理者是指一個類別可以作為其它東西的介面。代理者可以作任何東西的介面:網路連接、記憶體中的大物件、檔案或其它昂貴或無法複製的資源。

概述
著名的代理模式例子為參照計數(英語:reference counting)指標物件。當一個複雜物件的多份副本須存在時,代理模式可以結合享元模式以減少記憶體用量。典型作法是建立一個複雜物件及多個代理者,每個代理者會參照到原本的複雜物件。而作用在代理者的運算會轉送到原本物件。一旦所有的代理者都不存在時,複雜物件會被移除。
結構

在上面的UML類圖中,Proxy
類實現了Subject
接口,使它充當Subject
對象的代替者。它維護一個引用(realSubject
)至被代替的對象(RealSubject
),使其可以轉發給它(realSubject.operation()
)。
序列圖展示了運行時交互:The Client
對象通過合作於Proxy
對象,來控制到RealSubject
對象的訪問。在這個例子中,Proxy
轉發請求至RealSubject
,它辦理這個請求。
示例
以下Java範例解釋惰性載入模式中的「虛擬代理」方法。ProxyImage
類別用來存取遠端方法。
import java.util.*;
interface Image {
public void displayImage();
}
//on System A
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
}
public void displayImage() {
System.out.println("Displaying " + filename);
}
}
//on System B
class ProxyImage implements Image {
private String filename;
private Image image;
public ProxyImage(String filename) {
this.filename = filename;
}
public void displayImage() {
if(image == null)
image = new RealImage(filename);
image.displayImage();
}
}
class ProxyExample {
public static void main(String[] args) {
Image image1 = new ProxyImage("HiRes_10MB_Photo1");
Image image2 = new ProxyImage("HiRes_10MB_Photo2");
image1.displayImage(); // loading necessary
image2.displayImage(); // loading necessary
}
}
程式的輸出為:
Loading HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Loading HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Remove ads
C#的例子:
using System;
namespace Proxy {
interface IImage {
void Display();
}
class RealImage : IImage {
public RealImage(string fileName) {
FileName = fileName;
LoadFromFile();
}
private void LoadFromFile() {
Console.WriteLine("Loading " + FileName);
}
public String FileName { get; private set; }
public void Display() {
Console.WriteLine("Displaying " + FileName);
}
}
class ProxyImage : IImage {
public ProxyImage(string fileName) {
FileName = fileName;
}
public String FileName { get; private set; }
private IImage image;
public void Display() {
if (image == null)
image = new RealImage(FileName);
image.Display();
}
}
class Program {
static void Main(string[] args) {
IImage image = new ProxyImage("HiRes_Image");
for (int i = 0; i < 10; i++)
image.Display();
}
}
}
程式的輸出為:
Loading HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Displaying HiRes_Image
Remove ads
from abc import ABC, abstractmethod
class Image(ABC):
@abstractmethod
def display(self): pass
class RealImage(Image):
def __init__(self, filename):
self.filename = filename
self.load_from_disk()
def load_from_disk(self):
print("Loading ", self.filename)
def display(self):
print("Displaying ", self.filename)
class ProxyImage(Image):
def __init__(self, filename):
self.filename = filename
self.image = None
def display(self):
if self.image is None:
self.image = RealImage(self.filename)
self.image.display()
def example():
image1 = ProxyImage("HiRes_10MB_Photo1")
image2 = ProxyImage("HiRes_10MB_Photo2")
image1.display()
image2.display()
image1.display()
image2.display()
其執行:
>>> example()
Loading HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Loading HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo2
Remove ads
另見
引用
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads