Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В компьютерном программировании , то прокси - модель является разработка программного обеспечения шаблон . Прокси , в самом общем виде представляет собой функционирующую класс как интерфейс к чему - то еще. Прокси-сервер может взаимодействовать с чем угодно: сетевым подключением, большим объектом в памяти, файлом или каким-либо другим ресурсом, который стоит дорого или невозможно скопировать. Короче говоря, прокси - это объект-оболочка или агент, который вызывается клиентом для доступа к реальному обслуживающему объекту за кулисами. Использование прокси может быть просто пересылкойк реальному объекту, или может предоставить дополнительную логику. В прокси-сервере могут быть предоставлены дополнительные функции, например кэширование, когда операции с реальным объектом являются ресурсоемкими, или проверка предварительных условий перед вызовом операций с реальным объектом. Для клиента использование прокси-объекта аналогично использованию реального объекта, поскольку оба реализуют один и тот же интерфейс.

Обзор [ править ]

Шаблон проектирования Proxy [1] - это один из двадцати трех хорошо известных шаблонов проектирования GoF, которые описывают, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые легче реализовать, изменить, тестирование и повторное использование.

Какие проблемы может решить шаблон проектирования прокси? [2] [ редактировать ]

  • Доступ к объекту должен контролироваться.
  • При доступе к объекту должны быть предоставлены дополнительные функции.

Например, при доступе к конфиденциальным объектам должна быть возможность проверить наличие у клиентов необходимых прав доступа.

Какое решение описывает шаблон проектирования прокси? [ редактировать ]

Определите отдельный Proxyобъект, который

  • может использоваться как замена другого объекта ( Subject) и
  • реализует дополнительную функциональность для управления доступом к этому предмету.

Это позволяет работать с Proxyобъектом для выполнения дополнительных функций при доступе к субъекту. Например, чтобы проверить права доступа клиентов, обращающихся к чувствительному объекту.

Чтобы действовать вместо субъекта, прокси-сервер должен реализовывать Subjectинтерфейс. Клиенты не могут сказать, работают ли они с предметом или его прокси.

См. Также схему классов и последовательности UML ниже.

Структура [ править ]

Схема классов и последовательности UML [ править ]

Пример класса UML и диаграммы последовательности для шаблона проектирования прокси. [3]

В приведенной выше UML - диаграмме классов , то Proxyорудия класса Subjectинтерфейса , так что он может выступать в качестве замены для Subjectобъектов. Он поддерживает ссылку ( realSubject) на замещенный объект ( RealSubject), чтобы он мог пересылать запросы к нему ( realSubject.operation()).

Диаграмма последовательности показывает взаимодействия во время выполнения: Clientобъект работает через Proxyобъект, который управляет доступом к RealSubjectобъекту. В этом примере Proxyобъект пересылает запрос объекту RealSubject, который его выполняет.

Диаграмма классов [ править ]

Прокси в UML
Прокси в LePUS3 ( легенда )

Возможные сценарии использования [ править ]

Удаленный прокси [ править ]

При распределенной связи объектов локальный объект представляет удаленный объект (принадлежащий другому адресному пространству). Локальный объект является прокси для удаленного объекта, и вызов метода для локального объекта приводит к вызову удаленного метода для удаленного объекта. Примером может служить реализация банкомата , где банкомат может содержать прокси-объекты для банковской информации, которая существует на удаленном сервере.

Виртуальный прокси [ править ]

Вместо сложного или тяжелого объекта в некоторых случаях может быть предпочтительным каркасное изображение. Когда базовое изображение огромно по размеру, оно может быть представлено с помощью виртуального прокси-объекта, загружающего реальный объект по запросу.

Прокси-сервер защиты [ править ]

Прокси-сервер защиты может использоваться для управления доступом к ресурсу на основе прав доступа.

Пример [ править ]

C # [ править ]

интерфейс  ICar {  void  DriveCar ()  ; }// Открытый  класс  реального объекта Car  :  ICar {  public  void  DriveCar ()  {  Console . WriteLine ( «Машину проехали!» );  } }// Открытый  класс  прокси-объекта ProxyCar  :  ICar {  частный  драйвер  драйвера ;  частный  ICar  realCar ; public  ProxyCar ( драйвер  драйвера )  {  this . драйвер  =  водитель ;  это . realCar  =  новая  машина ();  } public  void  DriveCar ()  {  if  ( driver . Age  <  16 )  Console . WriteLine ( «Извините, водитель еще слишком молод для вождения.» );  еще  это . realCar . DriveCar ();  } }открытый  класс  Driver {  public  int  Age  {  получить ;  набор ;  } public  Driver ( int  age )  {  this . Возраст  =  возраст ;  } }// Как использовать вышеуказанный прокси-класс? private  void  btnProxy_Click ( отправитель объекта  , EventArgs e ) { ICar car = new ProxyCar ( новый драйвер ( 15 )); машина . DriveCar ();          car  =  новый  ProxyCar ( новый  драйвер ( 25 ));  машина . DriveCar (); }

Выход

Извините, водитель слишком молод для управления автомобилем.Машину пригнали!

Примечания:

  • Прокси-сервер может скрыть от клиента информацию о реальном объекте.
  • Прокси-сервер может выполнять оптимизацию как загрузку по запросу.
  • Прокси-сервер может выполнять дополнительную работу, например, аудит.
  • Шаблон проектирования прокси также известен как шаблон суррогатного проектирования.

C ++ [ править ]

#include  <iostream>#include  <память>class  ICar  {  public :  virtual  ~ ICar ()  {  std :: cout  <<  "Деструктор ICar!"  <<  std :: endl ;  } виртуальная  пустота  DriveCar ()  =  0 ; };class  Car  :  public  ICar  {  public :  void  DriveCar ()  override  {  std :: cout  <<  "Автомобиль проехал!"  <<  std :: endl ;  } };class  ProxyCar  :  public  ICar  {  public :  ProxyCar ( int  driver_age )  :  driver_age_ ( driver_age )  {} void  DriveCar ()  переопределить  {  if  ( driver_age_  >  16 )  {  real_car_ -> DriveCar ();  }  else  {  std :: cout  <<  "Извините, водитель слишком молод для вождения."  <<  std :: endl ;  }  } частное :  станд :: unique_ptr < ИКАР >  real_car_  =  станд :: make_unique < Car > ();  int  driver_age_ ; };Int  основной ()  {  станд :: unique_ptr < ИКАР >  автомобиль  =  станд :: make_unique < ProxyCar > ( 16 );  автомобиль -> DriveCar (); car  =  std :: make_unique < ProxyCar > ( 25 );  автомобиль -> DriveCar (); }

Кристалл [ править ]

абстрактный  класс  AbstractCar  abstract  def  drive endclass  Car  <  AbstractCar  def  drive  ставит  "Автомобиль проехал!"  конец конецclass  Возраст получателя драйвера  : Int32    def  инициализировать ( @age )  конец конецкласс  ProxyCar  <  AbstractCar  частный  добытчик  водитель  :  водитель  частный  добытчик  real_car  :  AbstractCar def  initialize ( @driver )  @real_car  =  Автомобиль . новый  конец def  drive,  если  драйвер . age  <=  16  ставит  «Извините, водитель слишком молод для управления автомобилем».  еще  @real_car . привод  конец  конец конец# Драйвер  программы =  Драйвер . новый ( 16 ) автомобиль  =  ProxyCar . новая ( водительская ) машина . водить машинуdriver  =  Драйвер . new ( 25 ) car  =  ProxyCar . новая ( водительская ) машина . водить машину

Выход

Извините, водитель слишком молод для управления автомобилем.Машину пригнали!

Delphi / Object Pascal [ править ]

// Модуль  шаблона Proxy Design DesignPattern . Прокси ;интерфейсtype  // Автомобильный интерфейс  ICar  =  interface  procedure  DriveCar ;  конец ; // Класс TCar, реализующий ICar  TCar  =  Class ( TInterfacedObject ,  ICar )  class  function  New :  ICar ;  процедура  DriveCar ;  Конец ; //  ID  интерфейса драйвераriver =  interface  function  Age :  Integer ;  конец ; // Класс TDriver, реализующий IDriver  TDriver  =  Class ( TInterfacedObject ,  IDriver )  private  FAge :  Integer ;  открытый  конструктор  Create ( Age :  Integer ) ;  Перегрузка ;  функция класса  New ( Возраст : Целое число ) : IDriver ; функция Возраст : Целое число ; Конец ;        // Прокси-объект  TProxyCar  =  Class ( TInterfacedObject ,  ICar )  private  FDriver :  IDriver ;  FRealCar :  ICar ;  публичный  конструктор  Create ( Driver :  IDriver ) ;  Перегрузка ;  функция класса  New ( Драйвер : IDriver ) : ICar ; процедура DriveCar ; Конец ;      выполнение{Реализация TCar} функция  класса TCar . Новое :  ICar ; begin  Результат  : =  Создать ; конец ;процедура  TCar . DriveCar ; begin  WriteLn ( «Машину проехали!» ) ; конец ;{Реализация TDriver}конструктор  TDriver . Создать ( Возраст :  Целое число ) ; begin  унаследовано  Create ;  FAge  : =  Возраст ; конец ; функция  класса TDriver . Новое ( Возраст :  Целое число ) :  IDriver ; begin  Результат  : =  Создать ( Возраст ) ; конец ;функция  TDriver . Возраст :  целое число ; begin  Результат  : =  FAge ; конец ;{Реализация TProxyCar}конструктор  TProxyCar . Создать ( Драйвер :  IDriver ) ; begin  унаследовано  Create ;  Сам . FDriver  : =  Драйвер ;  Сам . FRealCar  : =  TCar . Создать  AS  ICar ; конец ; функция  класса TProxyCar . Новое ( Драйвер :  IDriver ) :  ICar ; begin  Результат  : =  Создать ( Драйвер ) ; конец ;процедура  TProxyCar . DriveCar ; begin  if  ( FDriver . Age  <=  16 )  then  WriteLn ( 'Извините, драйвер слишком молод для управления.' )  else  FRealCar . DriveCar () ; конец ;конец .

использование

программа  Project1 ; {$ APPTYPE Console} использует  DesignPattern . Прокси  в  DesignPattern.Proxy.pas ; начать  TProxyCar . Новое ( TDriver . New ( 16 )) . DriveCar ;  TProxyCar . Новое ( TDriver . New ( 25 )) . DriveCar ; конец .

Выход

Извините, водитель слишком молод для управления автомобилем.Машину пригнали!

Java [ править ]

Следующий пример Java иллюстрирует шаблон «виртуальный прокси». Класс ProxyImage используется для доступа к удаленному методу.

В примере сначала создается интерфейс, по которому шаблон создает классы. Этот интерфейс содержит только один метод отображения изображения, называемый displayImage () , который должен быть закодирован всеми реализующими его классами.

Прокси-класс ProxyImage работает в другой системе, чем сам класс реального изображения, и может представлять реальное изображение RealImage там. Информация об изображении доступна с диска. Используя шаблон прокси, код ProxyImage избегает многократной загрузки изображения, получая доступ к нему из другой системы в режиме экономии памяти. Ленивая загрузка, продемонстрированная в этом примере, не является частью шаблона прокси, а просто преимуществом, которое стало возможным благодаря использованию прокси.

интерфейс  изображения  {  общедоступный  void  displayImage (); }// В системе класс  RealImage  реализует  изображение  {  private  final  String  filename ; / **  * Конструктор  * @param filename  * /  public  RealImage ( String  filename )  {  this . имя файла  =  имя файла ;  loadImageFromDisk ();  } / **  * Загружает изображение с диска  * /  private  void  loadImageFromDisk ()  {  System . из . println ( "Загрузка"  +  имя файла );  } / **  * Отображает изображение  * /  public  void  displayImage ()  {  System . из . println ( "Отображение"  +  имя файла );  } }// В системе B класс  ProxyImage  реализует  Image  {  private  final  String  filename ;  частное  изображение RealImage  ;  / **  * Конструктор  * @param filename  * /  public  ProxyImage ( String  filename )  {  this . имя файла  =  имя файла ;  } / **  * Отображает изображение  * /  public  void  displayImage ()  {  if  ( image  ==  null )  {  image  =  new  RealImage ( filename );  }  изображение . displayImage ();  } }class  ProxyExample  {  / **  * Тестовый метод  * /  public  static  void  main ( final  String []  arguments )  {  Image  image1  =  new  ProxyImage ( "HiRes_10MB_Photo1" );  Изображение  image2  =  новое  ProxyImage ( "HiRes_10MB_Photo2" ); изображение1 . displayImage ();  // загружаем необходимое  изображение1 . displayImage ();  // загрузка ненужной  image2 . displayImage ();  // загрузка необходимо  image2 . displayImage ();  // загружаем ненужное  изображение1 . displayImage ();  // загрузка ненужных  } }

Выход

Загрузка HiRes_10MB_Photo1Отображение HiRes_10MB_Photo1Отображение HiRes_10MB_Photo1Загрузка HiRes_10MB_Photo2Отображение HiRes_10MB_Photo2Отображение HiRes_10MB_Photo2Отображение HiRes_10MB_Photo1

JavaScript [ править ]

// Класс  драйвера  class Driver {  constructor  ( age )  {  this . age  =  age  } }// Класс  автомобиля  class Car {  drive  ()  {  console . log ( 'Машину проехали!' )  } }// прокси - класс автомобиля класса  ProxyCar  {  конструктор  ( драйвер )  {  это . car  =  new  Автомобиль ()  this . driver  =  driver  } drive  ()  {  if  ( this . driver . age  <=  16 )  {  console . log ( 'Извините, драйвер слишком молод для управления.' )  }  else  {  this . машина . drive ()  }  } }// Запускаем программу const  driver  =  new  Driver ( 16 ) const  car  =  new  ProxyCar ( driver ) car . диск ()Const  драйвер2  =  новый  драйвер ( 25 ) Const  car2  =  новый  ProxyCar ( драйвер2 ) car2 . диск ()

Выход

Извините, водитель слишком молод для управления автомобилем.Машину пригнали!

PHP [ править ]

<? php интерфейс  Изображение {  общедоступная  функция  displayImage (); }// В системе класс  RealImage  реализует  Image {  private  string  $ filename  =  null ; публичная  функция  __construct ( строка  $ filename )  {  $ this -> filename  =  $ filename ;  $ this -> loadImageFromDisk ();  } / **  * Загружает изображение с диска  * /  private  function  loadImageFromDisk ()  {  echo  "Loading { $ this -> filename } "  .  \ PHP_EOL ;  } / **  * Отображает изображение  * /  общедоступная  функция  displayImage ()  {  echo  "Отображение { $ this -> filename } "  .  \ PHP_EOL ;  } }// В системе B класс  ProxyImage  реализует  Image {  private  ? Изображение  $ image  =  null ;  частная  строка  $ filename  =  null ; публичная  функция  __construct ( строка  $ filename )  {  $ this -> filename  =  $ filename ;  } / **  * Отображает изображение  * /  общедоступная  функция  displayImage ()  {  if  ( $ this -> image  ===  null )  {  $ this -> image  =  new  RealImage ( $ this -> filename );  }  $ this -> изображение -> displayImage ();  } }$ image1  =  новый  ProxyImage ( "HiRes_10MB_Photo1" ); $ image2  =  новый  ProxyImage ( "HiRes_10MB_Photo2" );$ image1 -> displayImage ();  // Загрузка необходимого $ image1 -> displayImage ();  // Загрузка ненужных $ image2 -> displayImage ();  // Загрузка необходимого $ image2 -> displayImage ();  // Загружаем ненужное $ image1 -> displayImage ();  // Загружаем ненужное

Выход

Загрузка HiRes_10MB_Photo1 Отображение HiRes_10MB_Photo1 Отображение HiRes_10MB_Photo1 Загрузка HiRes_10MB_Photo2 Отображение HiRes_10MB_Photo2 Отображение HiRes_10MB_Photo2 Отображение HiRes_10MB_Photo1

Python [ править ]

«» « Шаблон Пример прокси. „“» От  аЬса  импорт  ABCMeta ,  abstractmethodNOT_IMPLEMENTED  =  "Вы должны это реализовать."класс  AbstractCar :  __metaclass__  =  ABCMeta @abstractmethod  def  drive ( self ):  поднять  NotImplementedError ( NOT_IMPLEMENTED )class  Car ( AbstractCar ):  def  drive ( self )  ->  None :  print ( «Автомобиль проехал!» )class  Driver :  def  __init__ ( self ,  age :  int )  ->  None :  self . age  =  возрастclass  ProxyCar ( AbstractCar ):  def  __init__ ( self ,  driver )  ->  None :  self . car  =  Автомобиль ()  self . driver  =  водитель def  drive ( self )  ->  None :  если  self . водитель . age  <=  16 :  print ( «Извините, водитель слишком молод для управления.» )  else :  self . машина . диск ()driver  =  Driver ( 16 ) car  =  ProxyCar ( водитель ) автомобиль . диск ()driver  =  Driver ( 25 ) car  =  ProxyCar ( водитель ) автомобиль . диск ()

Выход

Извините, водитель слишком молод для управления автомобилем.Машину пригнали!

Ржавчина [ править ]

trait ICar {   fn  drive ( & self );}struct  Car {} impl ICar for Car {     fn  drive ( & self ) {  println ! ( «Машину пригнали!» ); }}impl Car {   fn  new ()  -> Автомобиль {  Автомобиль {}  }}struct  ProxyCar <' a > {  real_car : & ' ИКАР ,  driver_age : i32 ,}impl <' a > ICar для ProxyCar <' a > {     fn  drive ( & self ) {  если сам . driver_age > 16 {     я . real_car . диск (); } else {   println ! ( «Извините, водитель слишком молод, чтобы водить машину». ) } }}impl <' a > ProxyCar <' a > {   fn  new ( driver_age : i32 , other_car : & ' a ICar ) -> ProxyCar {     ProxyCar {  real_car : другой_кар , driver_age : driver_age , } }}# [cfg (тест)]mod  tests {  используйте super :: * ;   #[тест] fn  test_underage () {  let car = Car :: new ();    let proxy_car = ProxyCar :: new ( 16 , & автомобиль );     proxy_car . диск (); } #[тест] fn  test_can_drive () {  let car = Car :: new ();    let proxy_car = ProxyCar :: new ( 17 , & автомобиль );     proxy_car . диск (); }}

Выход

Извините, машина слишком молода для вас.Машину пригнали!

См. Также [ править ]

  • Составной узор
  • Шаблон декоратора
  • Ленивая инициализация

Ссылки [ править ]

  1. ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон Уэсли. стр.  207ff . ISBN 0-201-63361-2.CS1 maint: несколько имен: список авторов ( ссылка )
  2. ^ «Шаблон проектирования прокси - проблема, решение и применимость» . w3sDesign.com . Проверено 12 августа 2017 .
  3. ^ «Шаблон проектирования прокси - структура и взаимодействие» . w3sDesign.com . Проверено 12 августа 2017 .

Внешние ссылки [ править ]

  • Гири, Дэвид (22 февраля 2002 г.). «Возьмите под свой контроль шаблон проектирования прокси» . JavaWorld . Проверено 20 июля 2020 .
  • PerfectJPattern Open Source Project , предоставляет компонентную реализацию шаблона прокси на Java
  • Сравнение адаптера, прокси и фасада на Wayback Machine (архивировано 11 марта 2012 г.)
  • Шаблон проектирования прокси
  • Пример реализации C ++ шаблона прокси на Wayback Machine (архивировано 19 октября 2014 г.)
  • Описание шаблона прокси из Портлендского репозитория шаблонов