热门问题
时间线
聊天
视角
代理模式
来自维基百科,自由的百科全书
Remove ads
代理模式(英语:proxy pattern),是程式设计中的一种设计模式。所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网络连接、存储器中的大物件、文件或其它昂贵或无法复制的资源。

概述
著名的代理模式例子为引用计数(英语:reference counting)指针物件。当一个复杂物件的多份副本须存在时,代理模式可以结合享元模式以减少存储器用量。典型作法是建立一个复杂物件及多个代理者,每个代理者会引用到原本的复杂物件。而作用在代理者的运算会转送到原本物件。一旦所有的代理者都不存在时,复杂物件会被移除。
结构

在上面的UML类图中,Proxy类实现了Subject接口,使它充当Subject对象的代替者。它维护一个引用(realSubject)至被代替的对象(RealSubject),使其可以转发给它(realSubject.operation())。
序列图展示了运行时交互:The Client对象通过合作于Proxy对象,来控制到RealSubject对象的访问。在这个例子中,Proxy转发请求至RealSubject,它办理这个请求。
示例
下面是C++的例子:
import std;
using std::string;
using std::unique_ptr;
// Subject Interface
class Image {
public:
virtual void display() const = 0;
virtual ~Image() = default;
};
// Real Subject (expensive to load)
class RealImage : public Image {
private:
string filename;
public:
explicit RealImage(const string& file):
filename{file} {
loadFromDisk();
}
void display() const override {
std::println("Displaying image: {}", filename);
}
private:
void loadFromDisk() const {
std::println("Loading image from disk: {}", filename);
}
};
// Proxy (controls access to RealImage)
class ProxyImage : public Image {
private:
string filename;
mutable unique_ptr<RealImage> realImage; // lazily created
public:
explicit ProxyImage(const string& file):
filename{file} {}
void display() const override {
if (!realImage) {
std::println("(Proxy) Loading image on demand...");
realImage = std::make_unique<RealImage>(filename);
}
realImage->display();
}
};
// Client code
int main() {
Image* img = new ProxyImage("photo.png");
// First display (should load)
img->display();
// Second display (should use cached image)
img->display();
delete img;
return 0;
}
Remove ads
以下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
