Загрузка...
скачать
Реферат на тему:

Proxy (шаблон проектирования)



План:

    Введение
  • 1 Цель
    • 1.1 Проблема
    • 1.2 Решение
  • 2 Преимущества и недостатки от применения
  • 3 Сфера применения
  • 4 Прокси и близкие к нему шаблоны[1]
  • 5 Примеры реализации[2]
    • 5.1 Java
    • 5.2 C++
    • 5.3 C#
    • 5.4 JavaScript
    • 5.5 Object Pascal
    • 5.6 Ruby
    • 5.7 PHP5
    • 5.8 ActionScript
    • 5.9 Python
    • 5.10 VB.NET
  • Литература

Введение

Шаблон Proxy (определяет объект-заместитель англ. surrogate иначе -заменитель англ. placeholder) — шаблон проектирования, который предоставляет объект, который контролирует доступ к другому объекту через перехват всех вызовов (выполняет функцию контейнера).


1. Цель

1.1. Проблема

Необходимо управлять доступом к объекту так, чтобы создавать громоздкие объекты «по требованию».

1.2. Решение

Создать суррогат громоздкого объекта. «Заместитель» хранит ссылку, которая позволяет заместителю обратиться к реальному субъекту (объект класса «Заместитель» может обращаться к объекту класса «Субъект», если интерфейсы «Реального Субъекта» и «Субъекта» одинаковы). Поскольку интерфейс «Реального Субъекта» идентичен интерфейсу «Субъекта», так, что «Заместителя» можно подставить вместо «Реального Субъекта», контролирует доступ к «Реальному Субъекту», может отвечать за создание или удаление «Реального Субъекта». «Субъект» определяет общий для «Реального Субъекта» и «Заместителя» интерфейс, так, что «Заместитель» может быть использован везде, где ожидается «Реальный Субъект». При необходимости запросы могут быть переадресованы «Заместителем» «Реальному Субъекту».

Диаграмма классов шаблона проектирования Proxy

Шаблон proxy бывает нескольких видов, а именно:

  • Удаленный заместитель (англ. remote proxies) : обеспечивает связь с «Субъектом», который находится в другом адресном пространстве или на удалённой машине. Так же может отвечать за кодирование запроса и его аргументов и отправку закодированного запроса реальному «Субъекту»,
  • Виртуальный заместитель (англ. virtual proxies): обеспечивает создание реального «Субъекта» только тогда, когда он действительно понадобится. Так же может кэшировать часть информации о реальном «Субъекте», чтобы отложить его создание,
  • Копировать-при-записи: обеспечивает копирование «субъекта» при выполнении клиентом определённых действий (частный случай «виртуального прокси»).
  • Защищающий заместитель (англ. protection proxies): может проверять, имеет ли вызывающий объект необходимые для выполнения запроса права.
  • Кэширующий прокси: обеспечивает временное хранение результатов расчёта до отдачи их множественным клиентам, которые могут разделить эти результаты.
  • Экранирующий прокси: защищает «Субъект» от опасных клиентов (или наоборот).
  • Синхронизирующий прокси: производит синхронизированный контроль доступа к «Субъекту» в асинхронной многопоточной среде.
  • Smart reference proxy: производит дополнительные действия, когда на «Субъект» создается ссылка, например, рассчитывает количество активных ссылок на «Субъект».

2. Преимущества и недостатки от применения

Преимущества:

  •  удаленный заместитель;
  •  виртуальный заместитель может выполнять оптимизацию;
  •  защищающий заместитель;
  • "умная" ссылка;
Недостатки
  • резкое увеличение времени отклика.

3. Сфера применения

Шаблон Proxy может применяться в случаях работы с сетевым соединением, с огромным объектом в памяти (или на диске) или с любым другим ресурсом, который сложно или тяжело копировать. Хорошо известный пример применения — объект, подсчитывающий число ссылок.

4. Прокси и близкие к нему шаблоны[1]

  • Адаптер обеспечивает отличающийся интерфейс к объекту.
  • Прокси обеспечивает тот же самый интерфейс.
  • Декоратор обеспечивает расширенный интерфейс.

5. Примеры реализации[2]

5.1. Java

Пример реализации  
public class Main {
 
        public static void main(String[] args) {
                // Create math proxy
                IMath p = new MathProxy();
 
                // Do the math
                System.out.println("4 + 2 = " + p.add(4, 2));
                System.out.println("4 - 2 = " + p.sub(4, 2));
                System.out.println("4 * 2 = " + p.mul(4, 2));
                System.out.println("4 / 2 = " + p.div(4, 2));
        }
}
 
/**
 * "Subject"
 */
public interface IMath {
 
        public double add(double x, double y);
 
        public double sub(double x, double y);
 
        public double mul(double x, double y);
 
        public double div(double x, double y);
}
 
/**
 * "Real Subject"
 */
public class Math implements IMath {
 
        public double add(double x, double y) {
                return x + y;
        }
 
        public double sub(double x, double y) {
                return x - y;
        }
 
        public double mul(double x, double y) {
                return x * y;
        }
 
        public double div(double x, double y) {
                return x / y;
        }
 
}
 
/**
 * "Proxy Object"
 */
public class MathProxy implements IMath {
 
        private Math math;
 
        public MathProxy() {
                math = new Math();
        }
 
        public double add(double x, double y) {
                return math.add(x, y);
        }
 
        public double sub(double x, double y) {
                return math.sub(x, y);
        }
 
        public double mul(double x, double y) {
                return math.mul(x, y);
        }
 
        public double div(double x, double y) {
                return math.div(x, y);
        }
}

5.2. C++

Пример реализации  
/**
 * "Subject"
 */
class IMath {
public:
    virtual double add(double x, double y) = 0;
    virtual double sub(double x, double y) = 0;
    virtual double mul(double x, double y) = 0;
    virtual double div(double x, double y) = 0;
};
 
/**
 * "Real Subject"
 */
class Math : public IMath {
public:
    double add(double x, double y) {
        return x + y;
    }
 
    double sub(double x, double y) {
        return x - y;
    }
 
    double mul(double x, double y) {
        return x * y;
    }
 
    double div(double x, double y) {
        return x / y;
    }
};
 
/**
 * "Proxy Object"
 */
class MathProxy : public IMath {
public:
    double add(double x, double y) {
        return math.add(x, y);
    }
 
    double sub(double x, double y) {
        return math.sub(x, y);
    }
 
    double mul(double x, double y) {
        return math.mul(x, y);
    }
 
    double div(double x, double y) {
        return math.div(x, y);
    }
 
private:
    Math math;
};
 
#include <iostream>
 
using std::cout;
using std::endl;
 
int main() {
 
    // Create math proxy
    MathProxy p;
 
    // Do the math
    cout << "4 + 2 = " << p.add(4, 2) << endl;
    cout << "4 - 2 = " << p.sub(4, 2) << endl;
    cout << "4 * 2 = " << p.mul(4, 2) << endl;
    cout << "4 / 2 = " << p.div(4, 2) << endl;
 
    return 0;
}

5.3. C#

Пример реализации  
  using System;
  using System.Threading;
 
  class MainApp
  {
    static void Main()
    {
      // Create math proxy
      IMath p = new MathProxy();
 
      // Do the math
      Console.WriteLine("4 + 2 = " + p.Add(4, 2));
      Console.WriteLine("4 - 2 = " + p.Sub(4, 2));
      Console.WriteLine("4 * 2 = " + p.Mul(4, 2));
      Console.WriteLine("4 / 2 = " + p.Div(4, 2));
 
      // Wait for user
      Console.Read();
    }
  }
 
  /// <summary>
  /// Subject - субъект
  /// </summary>
  /// <remarks>
  /// <li>
  /// <lu>определяет общий для <see cref="Math"/> и <see cref="Proxy"/> интерфейс, так что класс
  /// <see cref="Proxy"/> можно использовать везде, где ожидается <see cref="Math"/></lu>
  /// </li>
  /// </remarks>
  public interface IMath
  {
    double Add(double x, double y);
    double Sub(double x, double y);
    double Mul(double x, double y);
    double Div(double x, double y);
  }
 
 
  /// <summary>
  /// RealSubject - реальный объект
  /// </summary>
  /// <remarks>
  /// <li>
  /// <lu>определяет реальный объект, представленный заместителем</lu>
  /// </li>
  /// </remarks>
  class Math : IMath
  {
    public Math()
    {
        Console.WriteLine("Create object Math. Wait...");
        Thread.Sleep(1000);
    }
 
    public double Add(double x, double y){return x + y;}
    public double Sub(double x, double y){return x - y;}
    public double Mul(double x, double y){return x * y;}
    public double Div(double x, double y){return x / y;}
  }
 
  /// <summary>
  /// Proxy - заместитель
  /// </summary>
  /// <remarks>
  /// <li>
  /// <lu>хранит ссылку, которая позволяет заместителю обратиться к реальному
  /// субъекту. Объект класса <see cref="MathProxy"/> может обращаться к объекту класса
  /// <see cref="IMath"/>, если интерфейсы классов <see cref="Math"/> и <see cref="IMath"/> одинаковы;</lu>
  /// <lu>предоставляет интерфейс, идентичный интерфейсу <see cref="IMath"/>, так что заместитель
  /// всегда может быть предоставлен вместо реального субъекта;</lu>
  /// <lu>контролирует доступ к реальному субъекту и может отвечать за его создание 
  /// и удаление;</lu>
  /// <lu>прочие обязанности зависят от вида заместителя:
  /// <li>
  /// <lu><b>удаленный заместитель</b> отвечает за кодирование запроса и его аргументов
  /// и отправление закодированного запроса реальному субъекту в
  /// другом адресном пространстве;</lu>
  /// <lu><b>виртуальный заместитель</b> может кэшировать дополнительную информацию
  /// о реальном субъекте, чтобы отложить его создание.</lu>
  /// <lu><b>защищающий заместитель</b> проверяет, имеет ли вызывающий объект 
  /// необходимые для выполнения запроса права;</lu>
  /// </li>
  /// </lu>
  /// </li>
  /// </remarks>
  class MathProxy : IMath
  {
    Math math;
 
    public MathProxy()
    {
      math = null;
    }
 
    /// <summary>
    /// Быстрая операция - не требует реального субъекта
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public double Add(double x, double y)
    {
      return x + y;
    }
 
    public double Sub(double x, double y)
    {
      return x - y;
    }
 
    /// <summary>
    /// Медленная операция - требует создания реального субъекта
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public double Mul(double x, double y)
    {
      if (math == null)
          math = new Math();
      return math.Mul(x, y);
    }
 
    public double Div(double x, double y)
    {
      if (math == null)
          math = new Math();
      return math.Div(x, y);
    }
  }

5.4. JavaScript

Пример реализации  
/* Subject */
function IMath() {
        this.add = function(x, y) {};
        this.sub = function(x, y) {};
}
 
/* Real Subject */
function RMath() {
        /*
        IMath.call(this); // агрегируем IMath, т.к. нативного наследования нет
        // этот вариант следует использовать вместо прототипирования, 
        // если в IMath имеются приватные переменные, 
        // которые могут быть доступны через геттеры в IMath
        */
        this.add = function(x, y) {
                return x + y;
        };
        this.sub = function(x, y) {
                return x - y;
        };
}
RMath.prototype = new IMath();
RMath.prototype.constructor = RMath;
 
/* Proxy */
function MathProxy() {
        var math = new RMath();
 
        this.add = function(x, y) {
                return math.add(x, y);
        };
        this.sub = function(x, y) {
                return math.sub(x, y);
        };
}
 
var test = new MathProxy();
alert(test.add(3, 2)); // 5
alert(test.sub(3, 2)); // 1

5.5. Object Pascal

Пример реализации (пока нет)  
 

5.6. Ruby

Пример реализации  
#
# "Subject" - не нужен
#
 
#
# "Real Subject"
#
class Math
 
    def add(x, y); x + y; end
    def sub(x, y); x - y; end
    def mul(x, y); x * y; end
    def div(x, y); x / y; end
end
 
#
# "Proxy Object"
#
class MathProxy 
 
    def initialize
        @math = Math.new
    end
 
    def add(x, y); @math.add(x, y); end
    def sub(x, y); @math.sub(x, y); end
    def mul(x, y); @math.mul(x, y); end
    def div(x, y); @math.div(x, y); end
 
end
 
 
 
# Create math proxy
p = MathProxy.new;
 
# Do the math
puts "4 + 2 = #{p.add(4, 2)}"
puts "4 - 2 = #{p.sub(4, 2)}"
puts "4 * 2 = #{p.mul(4, 2)}"
puts "4 / 2 = #{p.div(4, 2)}"

5.7. PHP5

Пример реализации  
<?php
 
/// Subject - субъект
 
/// <lu>определяет общий для Math и "Proxy" интерфейс, так что класс
/// "Proxy" можно использовать везде, где ожидается 
interface IMath
{
    function Add($x, $y);
    function Sub($x, $y);
    function Mul($x, $y);
    function Div($x, $y);
}
 
 
 
  /// RealSubject - реальный объект
  /// определяет реальный объект, представленный заместителем
 
  class Math implements IMath
  {
    public function Math()
    {
        print ("Create object Math. Wait...");
        sleep(5);
    }
 
    public function  Add($x, $y){return $x + $y;}
    public function  Sub($x, $y){return $x - $y;}
    public function  Mul($x, $y){return $x * $y;}
    public function  Div($x, $y){return $x / $y;}
  }
 
 
  /// Proxy - заместитель
  /// хранит ссылку, которая позволяет заместителю обратиться к реальному
  /// субъекту. Объект класса "MathProxy" может обращаться к объекту класса
  /// "IMath", если интерфейсы классов "Math" и "IMath" одинаковы;
  /// предоставляет интерфейс, идентичный интерфейсу "IMath", так что заместитель
  /// всегда может быть предоставлен вместо реального субъекта;
  /// контролирует доступ к реальному субъекту и может отвечать за его создание 
  /// и удаление;
  /// прочие обязанности зависят от вида заместителя:
  /// удаленный заместитель отвечает за кодирование запроса и его аргументов
  /// и отправление закодированного запроса реальному субъекту в
  /// другом адресном пространстве;
  /// виртуальный заместитель может кэшировать дополнительную информацию
  /// о реальном субъекте, чтобы отложить его создание.
  /// защищающий заместитель проверяет, имеет ли вызывающий объект 
  /// необходимые для выполнения запроса права;
  class MathProxy implements IMath
  {
    protected $math;
 
    public function __construct()
    {
      $this->math = null;
    }
    /// Быстрая операция - не требует реального субъекта
    public function Add($x, $y)
    {
      return $x + $y;
    }
 
    public function  Sub($x, $y)
    {
      return $x - $y;
    }
 
 
    /// Медленная операция - требует создания реального субъекта
    public function Mul($x, $y)
    {
      if ($this->math == null)
          $this->math = new Math();
      return $this->math->Mul($x, $y);
    }
 
    public function Div($x, $y)
    {
      if ($this->math == null)
          $this->math = new Math();
      return $this->math->Div($x, $y);
    }
  }
      $p = new MathProxy;
 
      // Do the math
      print("4 + 2 = ".$p->Add(4, 2));
      print("4 - 2 = ".$p->Sub(4, 2));
      print("4 * 2 = ".$p->Mul(4, 2));
      print("4 / 2 = ".$p->Div(4, 2));
 
?>

5.8. ActionScript

Пример реализации  
//файл IMath.as
package
{
public interface IMath
{
        function add(a : Number, b : Number) : Number;
        function sub(a : Number, b : Number) : Number;
        function mul(a : Number, b : Number) : Number;
        function div(a : Number, b : Number) : Number;
}
}
 
//файл MathSubject.as
package
{
public class MathSubject implements IMath
{
        public function add(a : Number, b : Number) : Number
        {
                return a + b;
        }
 
        public function sub(a : Number, b : Number) : Number
        {
                return a - b;
        }
 
        public function mul(a : Number, b : Number) : Number
        {
                return a * b;
        }
 
        public function div(a : Number, b : Number) : Number
        {
                return a / b;
        }
}
}
 
//файл MathProxy.as
package
{
public class MathProxy implements IMath
{
        private var math : MathSubject;
 
        public function MathProxy()
        {
                math = new MathSubject();
        }
 
        public function add(a : Number, b : Number) : Number
        {
                return math.add(a, b);
        }
 
        public function sub(a : Number, b : Number) : Number
        {
                return math.sub(a, b);
        }
 
        public function mul(a : Number, b : Number) : Number
        {
                return math.mul(a, b);
        }
 
        public function div(a : Number, b : Number) : Number
        {
                if (b != 0)
                        return math.div(a, b);
                else
                {
                        trace("Division by zero.");
                        return Number.POSITIVE_INFINITY;
                }
        }
}
}
 
//файл Main.as
package
{
import flash.display.Sprite;
 
public class Main extends Sprite
{
        public function Main()
        {
                playWithMath(new MathSubject());
                playWithMath(new MathProxy());
        }
 
        public function playWithMath(math : IMath) : void
        {
                trace(math.add(5, 0));
                trace(math.sub(5, 0));
                trace(math.mul(5, 0));
                trace(math.div(5, 0));
        }
}
}

5.9. Python

Пример реализации  
# -*- coding: utf-8 -*-
 
class IMath:
    """Интерфейс для прокси и реального субъекта"""
    def add(self, x, y):
        raise NotImplementedError()
 
    def sub(self, x, y):
        raise NotImplementedError()
 
    def mul(self, x, y):
        raise NotImplementedError()
 
    def div(self, x, y):
        raise NotImplementedError()
 
class Math(IMath):
    """Реальный субъект"""
    def add(self, x, y):
        return x + y
 
    def sub(self, x, y):
        return x - y
 
    def mul(self, x, y):
        return x * y
 
    def div(self, x, y):
        return x / y
 
class Proxy(IMath):
    """Прокси"""
    def __init__(self):
        self.math = Math()
 
    def add(self, x, y):
        return self.math.add(x, y)
 
    def sub(self, x, y):
        return self.math.sub(x, y)
 
    def mul(self, x, y):
        return self.math.mul(x, y)
 
    def div(self, x, y):
        if y == 0:
            return float('inf') # Вернуть positive infinity
        return self.math.div(x, y)
 
p = Proxy()
x, y = 4, 2
print '4 + 2 = ' + str(p.add(x, y))
print '4 - 2 = ' + str(p.sub(x, y))
print '4 * 2 = ' + str(p.mul(x, y))
print '4 / 2 = ' + str(p.div(x, y))

5.10. VB.NET

Пример реализации  
Imports System.Threading
 
Class MainApp
    Shared Sub Main()
        ' Create math proxy
        Dim p As IMath = New MathProxy()
 
        ' Do the math
        Console.WriteLine("4 + 2 = " & p.Add(4, 2))
        Console.WriteLine("4 - 2 = " & p.Subtr(4, 2))
        Console.WriteLine("4 * 2 = " & p.Mul(4, 2))
        Console.WriteLine("4 / 2 = " & p.Div(4, 2))
 
        ' Wait for user
        Console.Read()
    End Sub
End Class
 
''' <summary>
''' Subject - субъект
''' </summary>
''' <remarks>
''' <li>
''' <lu>определяет общий для <see cref="Math"/> и <see cref="Proxy"/> интерфейс, так что класс
''' <see cref="Proxy"/> можно использовать везде, где ожидается <see cref="Math"/></lu>
''' </li>
''' </remarks>
Public Interface IMath
    Function Add(ByVal x As Double, ByVal y As Double) As Double
    Function Subtr(ByVal x As Double, ByVal y As Double) As Double
    Function Mul(ByVal x As Double, ByVal y As Double) As Double
    Function Div(ByVal x As Double, ByVal y As Double) As Double
End Interface
 
 
''' <summary>
''' RealSubject - реальный объект
''' </summary>
''' <remarks>
''' <li>
''' <lu>определяет реальный объект, представленный заместителем</lu>
''' </li>
''' </remarks>
Class Math
    Implements IMath
 
    Public Sub New()
        Console.WriteLine("Create object Math. Wait...")
        Thread.Sleep(1000)
    End Sub
 
    Public Function Add(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Add
        Return x + y
    End Function
 
    Public Function Subtr(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Subtr
        Return x - y
    End Function
 
    Public Function Mul(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Mul
        Return x * y
    End Function
 
    Public Function Div(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Div
        Return x / y
    End Function
 
End Class
 
''' <summary>
''' Proxy - заместитель
''' </summary>
''' <remarks>
''' <li>
''' <lu>хранит ссылку, которая позволяет заместителю обратиться к реальному
''' субъекту. Объект класса <see cref="MathProxy"/> может обращаться к объекту класса
''' <see cref="IMath"/>, если интерфейсы классов <see cref="Math"/> и <see cref="IMath"/> одинаковы;</lu>
''' <lu>предоставляет интерфейс, идентичный интерфейсу <see cref="IMath"/>, так что заместитель
''' всегда может быть предоставлен вместо реального субъекта;</lu>
''' <lu>контролирует доступ к реальному субъекту и может отвечать за его создание 
''' и удаление;</lu>
''' <lu>прочие обязанности зависят от вида заместителя:
''' <li>
''' <lu><b>удаленный заместитель</b> отвечает за кодирование запроса и его аргументов
''' и отправление закодированного запроса реальному субъекту в
''' другом адресном пространстве;</lu>
''' <lu><b>виртуальный заместитель</b> может кэшировать дополнительную информацию
''' о реальном субъекте, чтобы отложить его создание.</lu>
''' <lu><b>защищающий заместитель</b> проверяет, имеет ли вызывающий объект 
''' необходимые для выполнения запроса права;</lu>
''' </li>
''' </lu>
''' </li>
''' </remarks>
Class MathProxy
    Implements IMath
    Private math As Math = Nothing
 
    ''' <summary>
    ''' Быстрая операция - не требует реального субъекта
    ''' </summary>
    Public Function Add(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Add
        Return x + y
    End Function
 
    Public Function Subtr(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Subtr
        Return x - y
    End Function
 
    ''' <summary>
    ''' Медленная операция - требует создания реального субъекта
    ''' </summary>
    Public Function Mul(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Mul
        If math Is Nothing Then
            math = New Math()
        End If
        Return math.Mul(x, y)
    End Function
 
    Public Function Div(ByVal x As Double, ByVal y As Double) As Double Implements IMath.Div
        If math Is Nothing Then
            math = New Math()
        End If
        Return math.Div(x, y)
    End Function
End Class

Литература

  • CodeLIB.YOURS // Заместитель (Proxy)
скачать

Данный реферат составлен на основе статьи из русской Википедии. Синхронизация выполнена 10.07.11 09:00:39

Похожие рефераты: Шаблон делегирования (шаблон проектирования), Шаблон проектирования, Декоратор (шаблон проектирования), Интерфейс (шаблон проектирования), Итератор (шаблон проектирования), Строитель (шаблон проектирования), Команда (шаблон проектирования), Прототип (шаблон проектирования), Одиночка (шаблон проектирования).

Категории: Шаблоны проектирования, Объектно-ориентированное программирование.

Текст доступен по лицензии Creative Commons Attribution-ShareAlike.