![Заместитель](/images/patterns/cards/proxy-mini.png?id=25890b11e7dc5af29625ccd0678b63a8)
Заместитель на C#
Заместитель — это объект, который выступает прослойкой между клиентом и реальным сервисным объектом. Заместитель получает вызовы от клиента, выполняет свою функцию (контроль доступа, кеширование, изменение запроса и прочее), а затем передаёт вызов сервисному объекту.
Заместитель имеет тот же интерфейс, что и реальный объект, поэтому для клиента нет разницы — работать через заместителя или напрямую.
Сложность:
Популярность:
Применимость: Паттерн Заместитель применяется в C# коде тогда, когда надо заменить настоящий объект его суррогатом, причём незаметно для клиентов настоящего объекта. Это позволит выполнить какие-то добавочные поведения до или после основного поведения настоящего объекта.
Признаки применения паттерна: Класс заместителя чаще всего делегирует всю настоящую работу своему реальному объекту. Заместители часто сами следят за жизненным циклом своего реального объекта.
Концептуальный пример
Этот пример показывает структуру паттерна Заместитель, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.
Program.cs: Пример структуры паттерна
using System;
namespace RefactoringGuru.DesignPatterns.Proxy.Conceptual
{
// Интерфейс Субъекта объявляет общие операции как для Реального Субъекта,
// так и для Заместителя. Пока клиент работает с Реальным Субъектом,
// используя этот интерфейс, вы сможете передать ему заместителя вместо
// реального субъекта.
public interface ISubject
{
void Request();
}
// Реальный Субъект содержит некоторую базовую бизнес-логику. Как правило,
// Реальные Субъекты способны выполнять некоторую полезную работу, которая к
// тому же может быть очень медленной или точной – например, коррекция
// входных данных. Заместитель может решить эти задачи без каких-либо
// изменений в коде Реального Субъекта.
class RealSubject : ISubject
{
public void Request()
{
Console.WriteLine("RealSubject: Handling Request.");
}
}
// Интерфейс Заместителя идентичен интерфейсу Реального Субъекта.
class Proxy : ISubject
{
private RealSubject _realSubject;
public Proxy(RealSubject realSubject)
{
this._realSubject = realSubject;
}
// Наиболее распространёнными областями применения паттерна Заместитель
// являются ленивая загрузка, кэширование, контроль доступа, ведение
// журнала и т.д. Заместитель может выполнить одну из этих задач, а
// затем, в зависимости от результата, передать выполнение одноимённому
// методу в связанном объекте класса Реального Субъект.
public void Request()
{
if (this.CheckAccess())
{
this._realSubject.Request();
this.LogAccess();
}
}
public bool CheckAccess()
{
// Некоторые реальные проверки должны проходить здесь.
Console.WriteLine("Proxy: Checking access prior to firing a real request.");
return true;
}
public void LogAccess()
{
Console.WriteLine("Proxy: Logging the time of request.");
}
}
public class Client
{
// Клиентский код должен работать со всеми объектами (как с реальными,
// так и заместителями) через интерфейс Субъекта, чтобы поддерживать как
// реальные субъекты, так и заместителей. В реальной жизни, однако,
// клиенты в основном работают с реальными субъектами напрямую. В этом
// случае, для более простой реализации паттерна, можно расширить
// заместителя из класса реального субъекта.
public void ClientCode(ISubject subject)
{
// ...
subject.Request();
// ...
}
}
class Program
{
static void Main(string[] args)
{
Client client = new Client();
Console.WriteLine("Client: Executing the client code with a real subject:");
RealSubject realSubject = new RealSubject();
client.ClientCode(realSubject);
Console.WriteLine();
Console.WriteLine("Client: Executing the same client code with a proxy:");
Proxy proxy = new Proxy(realSubject);
client.ClientCode(proxy);
}
}
}
Output.txt: Результат выполнения
Client: Executing the client code with a real subject:
RealSubject: Handling Request.
Client: Executing the same client code with a proxy:
Proxy: Checking access prior to firing a real request.
RealSubject: Handling Request.
Proxy: Logging the time of request.