🎉 Ура! После трёх лет работы, я наконец выпустил английскую версию книги о паттернах! Вот она »

C#: Заместитель

Proxy Заместитель Proxy

Заместитель — это объект, который выступает прослойкой между клиентом и реальным сервисным объектом. Заместитель получает вызовы от клиента, выполняет свою функцию (контроль доступа, кеширование, изменение запроса и прочее), а затем передаёт вызов сервисному объекту.

Заместитель имеет тот же интерфейс, что и реальный объект, поэтому для клиента нет разницы — работать через заместителя или напрямую.

Подробней о Заместителе

Особенности паттерна на C#

Сложность:

Популярность:

Применимость: Паттерн Заместитель применяется в C# коде тогда, когда надо заменить настоящий объект его суррогатом, причём незаметно для клиентов настоящего объекта. Это позволит выполнить какие-то добавочные поведения до или после основного поведения настоящего объекта.

Признаки применения паттерна: Класс заместителя чаще всего делегирует всю настоящую работу своему реальному объекту. Заместители часто сами следят за жизненным циклом своего реального объекта.

Пример: Структура паттерна

Этот пример показывает структуру паттерна Заместитель, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.

Program.cs: Пример структуры паттерна

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RefactoringGuru.DesignPatterns.Proxy.Structural
{
    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();

            client.ClientCode(proxy);
        }
    }

    public class Client
    {
        public void ClientCode(Subject subject)
        {
            subject.Request();
        }
    }

    public abstract class Subject
    {
        public abstract void Request();
    }

    class RealSubject : Subject
    {
        public override void Request()
        {
            Console.WriteLine("RealSubject: Handling Request.");
        }
    }

    class Proxy : Subject
    {
        RealSubject realSubject;
        
        public override void Request()
        {
            if (this.checkAccess())
            {
                realSubject = new RealSubject();
                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.");
        }
    }
}

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.