热门问题
时间线
聊天
视角
代理模式
来自维基百科,自由的百科全书
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
下面是Python的例子:
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