Proxy (patró de disseny)![]() ![]() En programació, el patró proxy és un patró de disseny de programari. Un proxy, en la seva forma més general, és una classe que funciona com una interfície a una altra cosa. L'altra cosa podria ser qualsevol: una connexió a la xarxa, un gran objecte en la memòria, un arxiu, o algun altre recurs que és car o impossible de duplicar. Un exemple ben conegut dels proxys és d'intermediari en un model referenciat amb punters a objectes. En els casos que hi ha vaires còpies d'un objecte complex el patró proxy pot ser adaptat per incorporar al patró Flyweight per tal de reduir la necessitat de memòria. Codis d'exempleJavaEl següent exemple en Java implementa el patró "virtual proxy". La sortida del programa és: Loading HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Loading HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo1 La classe import java.util.*;
interface Image {
public void displayImage();
}
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {
// Potentially expensive operation
// ...
System.out.println("Loading "+filename);
}
public void displayImage() { System.out.println("Displaying "+filename); }
}
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); // load only on demand
}
image.displayImage();
}
}
class ProxyExample {
public static void main(String[] args) {
Image image1 = new ProxyImage("HiRes_10MB_Photo1");
Image image2 = new ProxyImage("HiRes_10MB_Photo2");
Image image3 = new ProxyImage("HiRes_10MB_Photo3");
image1.displayImage(); // loading necessary
image2.displayImage(); // loading necessary
image1.displayImage(); // no loading necessary; already done
// the third image will never be loaded - time saved!
}
}
Python#!/opt/env/python
class Image(object):
def display(self):
pass
class RealImage(Image):
def __init__(self, name):
self.name = name
self.load()
def load(self):
print "Loading...", self.name
def display(self):
print "Displaying...", self.name
class ProxyImage(Image):
def __init__(self, name):
self.name = name
self.test = None
def display(self):
if not self.test:
self.test = RealImage(self.name)
self.test.display()
def main():
t1 = ProxyImage("big_image1.png")
t2 = ProxyImage("big_image2.png")
t3 = ProxyImage("big_image3.png")
t1.display() # loads, displays
t2.display() # loads, displays
t1.display() # displays
# t3.display() # no display, no load
return
if __name__ == "__main__":
main()
C#En aquest exemple de C #, el En aquest exemple, thePassword és la contrasenya correcta. using System;
namespace ConsoleApplicationTest.FundamentalPatterns.ProtectionProxyPattern
{
public interface IClient {
string GetAccountNo();
}
public class RealClient : IClient {
private string accountNo = "12345";
public RealClient() {
Console.WriteLine("RealClient: Initialized");
}
public string GetAccountNo() {
Console.WriteLine("RealClient's AccountNo: " + accountNo);
return accountNo;
}
}
public class ProtectionProxy : IClient
{
private string password; //password to get secret
RealClient client;
public ProtectionProxy(string pwd) {
Console.WriteLine("ProtectionProxy: Initialized");
password = pwd;
client = new RealClient();
}
// Authenticate the user and return the Account Number
public String GetAccountNo() {
Console.Write("Password: ");
string tmpPwd = Console.ReadLine();
if (tmpPwd == password) {
return client.GetAccountNo();
} else {
Console.WriteLine("ProtectionProxy: Illegal password!");
return "";
}
}
}
class ProtectionProxyExample
{
[STAThread]
public static void Main(string[] args) {
IClient client = new ProtectionProxy("thePassword");
Console.WriteLine();
Console.WriteLine("main received: " + client.GetAccountNo());
Console.WriteLine("\nPress any key to continue . . .");
Console.Read();
}
}
}
C++#include <string>
#include <iostream>
class Image //abstract
{
protected:
Image() {}
public:
virtual ~Image() {}
virtual void displayImage() = 0;
};
class RealImage : public Image
{
public:
explicit RealImage(std::string filename)
{
this->filename = filename;
loadImageFromDisk();
}
void displayImage()
{
std::cout<<"Displaying "<<filename<<std::endl;
}
private:
void loadImageFromDisk()
{
// Potentially expensive operation
// ...
std::cout<<"Loading "<<filename<<std::endl;
}
std::string filename;
};
class ProxyImage : public Image
{
public:
explicit ProxyImage(std::string filename)
{
this->filename = filename;
this->image = nullptr;
}
~ProxyImage() { delete image; }
void displayImage()
{
if (image == nullptr) {
image = new RealImage(filename); // load only on demand
}
image->displayImage();
}
private:
std::string filename;
Image* image;
};
int main(int argc, char* argv[])
{
std::cout<<"main"<<std::endl;
Image* image1 = new ProxyImage("HiRes_10MB_Photo1");
Image* image2 = new ProxyImage("HiRes_10MB_Photo2");
Image* image3 = new ProxyImage("HiRes_10MB_Photo3");
image1->displayImage(); // loading necessary
image2->displayImage(); // loading necessary
image1->displayImage(); // no loading necessary; already done
// the third image will never be loaded - time saved!
delete image1;
delete image2;
delete image3;
return 0;
}
PerlThe Perl with Moose implementation. The "lazy" option is used to delay the expensive operation. The "handles" option is used to create the delegation to proxied class. use MooseX::Declare;
role Image {
requires 'display_image';
}
class RealImage with Image {
has 'filename' => (
isa => 'Str',
);
# Moose's constructor
method BUILD ($params) {
$self->_load_image_from_disk;
}
method _load_image_from_disk () {
# Expensive operation
print "Loading " . $self->{filename} . "\n";
}
method display_image () {
print "Displaying " . $self->{filename} . "\n";
}
}
class ProxyImage with Image {
has 'filename' => (
isa => 'Str',
);
has 'image' => (
does => 'Image',
lazy => 1, # default value is loaded only on demand
default => sub { RealImage->new(filename => $_[0]->{filename}) },
handles => [ 'display_image' ], # automatic delegation
);
}
class ProxyExample {
# Moose's constructor
method BUILD ($params) {
my $image1 = ProxyImage->new(filename=>'HiRes_10MB_Photo1');
my $image2 = ProxyImage->new(filename=>'HiRes_10MB_Photo2');
my $image3 = ProxyImage->new(filename=>'HiRes_10MB_Photo3');
$image1->display_image; # loading necessary
$image2->display_image; # loading necessary
$image1->display_image; # already done
# the third image will never be loaded - time saved!
}
}
ProxyExample->new;
Vegeu també
Enllaços externs
|
Portal di Ensiklopedia Dunia