Заместитель | |
---|---|
Proxy | |
| |
Тип | структурный |
Назначение | Предоставляет суррогатный объект, управляющий доступом к другому объекту. |
Плюсы |
|
Минусы |
|
Описан в Design Patterns | Да |
Заместитель (англ. Proxy) — структурный шаблон проектирования, предоставляющий объект, который контролирует доступ к другому объекту, перехватывая все вызовы (выполняет функцию контейнера).
Необходимо контролировать доступ к объекту, не изменяя при этом поведение клиента.
Необходимо иметь доступ к объекту так, чтобы не создавать реальные объекты непосредственно, а через другой объект, который может иметь дополнительную функциональность.
Создать суррогат реального объекта. «Заместитель» хранит ссылку, которая позволяет заместителю обратиться к реальному субъекту (объект класса «Заместитель» может обращаться к объекту класса «Субъект», если интерфейсы «Реального Субъекта» и «Субъекта» одинаковы). Поскольку интерфейс «Реального Субъекта» идентичен интерфейсу «Субъекта», так, что «Заместителя» можно подставить вместо «Реального Субъекта», контролирует доступ к «Реальному Субъекту», может отвечать за создание или удаление «Реального Субъекта». «Субъект» определяет общий для «Реального Субъекта» и «Заместителя» интерфейс так, что «Заместитель» может быть использован везде, где ожидается «Реальный Субъект». При необходимости запросы могут быть переадресованы «Заместителем» «Реальному Субъекту».
Шаблон Proxy может применяться в случаях работы с сетевым соединением, с огромным объектом в памяти (или на диске) или с любым другим ресурсом, который сложно или тяжело копировать. Хорошо известный пример применения — объект, подсчитывающий число ссылок.
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 double add(double x, double y) {
if(math == null) {
math = new Math();
}
return math.add(x, y);
}
public double sub(double x, double y) {
if(math == null) {
math = new Math();
}
return math.sub(x, y);
}
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);
}
}
object Main extends App {
val p: IMath = new MathProxy
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"
*/
trait IMath {
def add(x: Double, y: Double): Double
def sub(x: Double, y: Double): Double
def mul(x: Double, y: Double): Double
def div(x: Double, y: Double): Double
}
/**
* "Real Subject"
*/
class Math extends IMath {
def add(x: Double, y: Double) = x + y
def sub(x: Double, y: Double) = x - y
def mul(x: Double, y: Double) = x * y
def div(x: Double, y: Double) = x / y
}
/**
* "Proxy Object"
*/
class MathProxy extends IMath {
private lazy val math = new Math
def add(x: Double, y: Double) = math.add(x, y)
def sub(x: Double, y: Double) = math.sub(x, y)
def mul(x: Double, y: Double) = math.mul(x, y)
def div(x: Double, y: Double) = math.div(x, y)
}
/**
* "Subject"
*/
class IMath
{
public:
virtual double add(double, double) = 0;
virtual double sub(double, double) = 0;
virtual double mul(double, double) = 0;
virtual double div(double, double) = 0;
};
/**
* "Real Subject"
*/
class Math : public IMath
{
public:
virtual double add(double x, double y)
{
return x + y;
}
virtual double sub(double x, double y)
{
return x - y;
}
virtual double mul(double x, double y)
{
return x * y;
}
virtual double div(double x, double y)
{
return x / y;
}
};
/**
* "Proxy Object"
*/
class MathProxy : public IMath
{
public:
MathProxy()
{
math = new Math();
}
virtual ~MathProxy()
{
delete math;
}
virtual double add(double x, double y)
{
return math->add(x, y);
}
virtual double sub(double x, double y)
{
return math->sub(x, y);
}
virtual double mul(double x, double y)
{
return math->mul(x, y);
}
virtual double div(double x, double y)
{
return math->div(x, y);
}
private:
IMath *math;
};
#include <iostream>
using std::cout;
using std::endl;
int main()
{
// Create math proxy
IMath *proxy = new MathProxy();
// Do the math
cout << "4 + 2 = " << proxy->add(4, 2) << endl;
cout << "4 - 2 = " << proxy->sub(4, 2) << endl;
cout << "4 * 2 = " << proxy->mul(4, 2) << endl;
cout << "4 / 2 = " << proxy->div(4, 2) << endl;
delete proxy;
return 0;
}
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);
}
}
/* 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
#
# "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)}"
<?php
/// Subject - субъект
/// определяет общий для 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 __construct()
{
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" может обращаться к объекту класса
/// "Math", если интерфейсы классов "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));
?>
//файл 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));
}
}
}
# -*- 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 = None
# Быстрые операции - не требуют реального субъекта
def add(self, x, y):
return x + y
def sub(self, x, y):
return x - y
# Медленная операция - требует создания реального субъекта
def mul(self, x, y):
if not self.math:
self.math = Math()
return self.math.mul(x, y)
def div(self, x, y):
if y == 0:
return float('inf') # Вернуть positive infinity
if not self.math:
self.math = Math()
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))
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
Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .