代理
外观
控制对对象的访问。
该示例首先创建了一个接口,模式在该接口上创建类。此接口仅包含一个用于显示图像的方法,称为displayImage()
,该方法必须由所有实现它的类进行编码。
代理类ProxyImage
运行在与真实图像类本身不同的系统上,并且可以在那里代表真实的图像RealImage
。图像信息从磁盘访问。使用代理模式,ProxyImage
的代码避免了多次加载图像,并以节省内存的方式从另一个系统访问图像。
C# 实现
interface ICar
{
void DriveCar() ;
}
// Real Object
public class Car : ICar
{
public void DriveCar()
{
Console.WriteLine("Car has been driven!");
}
}
// Proxy Object
public class ProxyCar : ICar
{
private Driver driver;
private ICar realCar;
public ProxyCar(Driver driver)
{
this.driver = driver;
this.realCar = new Car();
}
public void DriveCar()
{
if (driver.Age < 16)
Console.WriteLine("Sorry, the driver is too young to drive.");
else
this.realCar.DriveCar();
}
}
public class Driver
{
public int Age { get; set; }
public Driver(int age)
{
this.Age = age;
}
}
// How to use above Proxy class?
private void btnProxy_Click(object sender, EventArgs e)
{
ICar car = new ProxyCar(new Driver(15));
car.DriveCar();
car = new ProxyCar(new Driver(25));
car.DriveCar();
}
输出
Sorry, the driver is too young to drive. Car has been driven!
注意
- 代理可以向客户端隐藏有关真实对象的信息。
- 代理可以执行优化,例如按需加载。
- 代理可以执行额外的维护工作,例如审计任务。
- 代理设计模式也被称为替身设计模式。
另一个例子
using System;
namespace Proxy
{
class Program
{
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();
}
}
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
C++ 实现
#include <iostream>
#include <memory>
class ICar {
public:
virtual ~ICar() { std::cout << "ICar destructor!\n"; }
virtual void DriveCar() = 0;
};
class Car : public ICar {
public:
void DriveCar() override { std::cout << "Car has been driven!\n"; }
};
class ProxyCar : public ICar {
public:
ProxyCar(int driver_age) : driver_age_(driver_age) {}
void DriveCar() override {
if (driver_age_ > 16) {
real_car_->DriveCar();
} else {
std::cout << "Sorry, the driver is too young to drive.\n";
}
}
private:
std::unique_ptr<ICar> real_car_ = std::make_unique<Car>();
int driver_age_;
};
int main() {
std::unique_ptr<ICar> car = std::make_unique<ProxyCar>(16);
car->DriveCar();
car = std::make_unique<ProxyCar>(25);
car->DriveCar();
}
Crystal 实现
abstract class AbstractCar
abstract def drive
end
class Car < AbstractCar
def drive
puts "Car has been driven!"
end
end
class Driver
getter age : Int32
def initialize(@age)
end
end
class ProxyCar < AbstractCar
private getter driver : Driver
private getter real_car : AbstractCar
def initialize(@driver)
@real_car = Car.new
end
def drive
if driver.age <= 16
puts "Sorry, the driver is too young to drive."
else
@real_car.drive
end
end
end
# Program
driver = Driver.new(16)
car = ProxyCar.new(driver)
car.drive
driver = Driver.new(25)
car = ProxyCar.new(driver)
car.drive
输出
Sorry, the driver is too young to drive. Car has been driven!
Delphi 实现
// Proxy Design pattern
unit DesignPattern.Proxy;
interface
type
// Car Interface
ICar = interface
procedure DriveCar;
end;
// TCar class, implementing ICar
TCar = Class(TInterfacedObject, ICar)
class function New: ICar;
procedure DriveCar;
End;
// Driver Interface
IDriver = interface
function Age: Integer;
end;
// TDriver Class, implementing IDriver
TDriver = Class(TInterfacedObject, IDriver)
private
FAge: Integer;
public
constructor Create(Age: Integer); Overload;
class function New(Age: Integer): IDriver;
function Age: Integer;
End;
// Proxy Object
TProxyCar = Class(TInterfacedObject, ICar)
private
FDriver: IDriver;
FRealCar: ICar;
public
constructor Create(Driver: IDriver); Overload;
class function New(Driver: IDriver): ICar;
procedure DriveCar;
End;
implementation
{ TCar Implementation }
class function TCar.New: ICar;
begin
Result := Create;
end;
procedure TCar.DriveCar;
begin
WriteLn('Car has been driven!');
end;
{ TDriver Implementation }
constructor TDriver.Create(Age: Integer);
begin
inherited Create;
FAge := Age;
end;
class function TDriver.New(Age: Integer): IDriver;
begin
Result := Create(Age);
end;
function TDriver.Age: Integer;
begin
Result := FAge;
end;
{ TProxyCar Implementation }
constructor TProxyCar.Create(Driver: IDriver);
begin
inherited Create;
Self.FDriver := Driver;
Self.FRealCar := TCar.Create AS ICar;
end;
class function TProxyCar.New(Driver: IDriver): ICar;
begin
Result := Create(Driver);
end;
procedure TProxyCar.DriveCar;
begin
if (FDriver.Age <= 16)
then WriteLn('Sorry, the driver is too young to drive.')
else FRealCar.DriveCar();
end;
end.
用法
program Project1;
{$APPTYPE Console}
uses
DesignPattern.Proxy in 'DesignPattern.Proxy.pas';
begin
TProxyCar.New(TDriver.New(16)).DriveCar;
TProxyCar.New(TDriver.New(25)).DriveCar;
end.
输出
Sorry, the driver is too young to drive. Car has been driven!
Java 实现
以下 Java 示例说明了“虚拟代理”模式。ProxyImage
类用于访问远程方法。
该示例首先创建了一个接口,模式在该接口上创建类。此接口仅包含一个用于显示图像的方法,称为displayImage()
,该方法必须由所有实现它的类进行编码。
代理类ProxyImage
运行在与真实图像类本身不同的系统上,并且可以在那里代表真实的图像RealImage
。图像信息从磁盘访问。使用代理模式,ProxyImage
的代码避免了多次加载图像,并以节省内存的方式从另一个系统访问图像。此示例中演示的延迟加载不是代理模式的一部分,而仅仅是使用代理所带来的优势。
interface Image {
public void displayImage();
}
// On System A
class RealImage implements Image {
private final String filename;
/**
* Constructor
* @param filename
*/
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
/**
* Loads the image from the disk
*/
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
}
/**
* Displays the image
*/
public void displayImage() {
System.out.println("Displaying " + filename);
}
}
// On System B
class ProxyImage implements Image {
private final String filename;
private RealImage image;
/**
* Constructor
* @param filename
*/
public ProxyImage(String filename) {
this.filename = filename;
}
/**
* Displays the image
*/
public void displayImage() {
if (image == null) {
image = new RealImage(filename);
}
image.displayImage();
}
}
class ProxyExample {
/**
* Test method
*/
public static void main(final String[] arguments) {
Image image1 = new ProxyImage("HiRes_10MB_Photo1");
Image image2 = new ProxyImage("HiRes_10MB_Photo2");
image1.displayImage(); // loading necessary
image1.displayImage(); // loading unnecessary
image2.displayImage(); // loading necessary
image2.displayImage(); // loading unnecessary
image1.displayImage(); // loading unnecessary
}
}
输出
Loading HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Loading HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo1
JavaScript 实现
// Driver class
class Driver {
constructor (age) {
this.age = age
}
}
// Car class
class Car {
drive () {
console.log('Car has been driven!')
}
}
// Proxy car class
class ProxyCar {
constructor (driver) {
this.car = new Car()
this.driver = driver
}
drive () {
if (this.driver.age <= 16) {
console.log('Sorry, the driver is too young to drive.')
} else {
this.car.drive()
}
}
}
// Run program
const driver = new Driver(16)
const car = new ProxyCar(driver)
car.drive()
const driver2 = new Driver(25)
const car2 = new ProxyCar(driver2)
car2.drive()
输出
Sorry, the driver is too young to drive. Car has been driven!
更高级的代理涉及Proxy
对象,该对象可以拦截和重新定义基本操作,例如访问属性。在这种情况下,处理程序函数有时被称为陷阱。[1]
PHP 实现
<?php
interface Image
{
public function displayImage();
}
// On System A
class RealImage implements Image
{
private string $filename = null;
public function __construct(string $filename)
{
$this->filename = $filename;
$this->loadImageFromDisk();
}
/**
* Loads the image from the disk
*/
private function loadImageFromDisk()
{
echo "Loading {$this->filename}" . \PHP_EOL;
}
/**
* Displays the image
*/
public function displayImage()
{
echo "Displaying {$this->filename}" . \PHP_EOL;
}
}
// On System B
class ProxyImage implements Image
{
private ?Image $image = null;
private string $filename = null;
public function __construct(string $filename)
{
$this->filename = $filename;
}
/**
* Displays the image
*/
public function displayImage()
{
if ($this->image === null) {
$this->image = new RealImage($this->filename);
}
$this->image->displayImage();
}
}
$image1 = new ProxyImage("HiRes_10MB_Photo1");
$image2 = new ProxyImage("HiRes_10MB_Photo2");
$image1->displayImage(); // Loading necessary
$image1->displayImage(); // Loading unnecessary
$image2->displayImage(); // Loading necessary
$image2->displayImage(); // Loading unnecessary
$image1->displayImage(); // Loading unnecessary
输出
Loading HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Loading HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo1
Python 实现
"""
Proxy pattern example.
"""
from abc import ABCMeta, abstractmethod
NOT_IMPLEMENTED = "You should implement this."
class AbstractCar:
__metaclass__ = ABCMeta
@abstractmethod
def drive(self):
raise NotImplementedError(NOT_IMPLEMENTED)
class Car(AbstractCar):
def drive(self) -> None:
print("Car has been driven!")
class Driver:
def __init__(self, age: int) -> None:
self.age = age
class ProxyCar(AbstractCar):
def __init__(self, driver) -> None:
self.car = Car()
self.driver = driver
def drive(self) -> None:
if self.driver.age <= 16:
print("Sorry, the driver is too young to drive.")
else:
self.car.drive()
driver = Driver(16)
car = ProxyCar(driver)
car.drive()
driver = Driver(25)
car = ProxyCar(driver)
car.drive()
输出
Sorry, the driver is too young to drive. Car has been driven!
Rust 实现
trait ICar {
fn drive(&self);
}
struct Car {}
impl ICar for Car {
fn drive(&self) {
println!("Car has been driven!");
}
}
impl Car {
fn new() -> Car {
Car {}
}
}
struct ProxyCar<'a> {
real_car: &'a ICar,
driver_age: i32,
}
impl<'a> ICar for ProxyCar<'a> {
fn drive(&self) {
if self.driver_age > 16 {
self.real_car.drive();
} else {
println!("Sorry, the driver is too young to drive.")
}
}
}
impl<'a> ProxyCar<'a> {
fn new(driver_age: i32, other_car: &'a ICar) -> ProxyCar {
ProxyCar {
real_car: other_car,
driver_age: driver_age,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_underage() {
let car = Car::new();
let proxy_car = ProxyCar::new(16, &car);
proxy_car.drive();
}
#[test]
fn test_can_drive() {
let car = Car::new();
let proxy_car = ProxyCar::new(17, &car);
proxy_car.drive();
}
}
输出
Sorry, the car is to young for you to drive. Car has been driven!
- ↑ "Proxy - JavaScript | MDN". developer.mozilla.org. Retrieved 21 January 2022.