Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!
Заместитель

Заместитель на Ruby

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

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

Сложность:

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

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

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

Концептуальный пример

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

main.rb: Пример структуры паттерна

# Интерфейс Субъекта объявляет общие операции как для Реального Субъекта, так и
# для Заместителя. Пока клиент работает с Реальным Субъектом, используя этот
# интерфейс, вы сможете передать ему заместителя вместо реального субъекта.
#
# @abstract
class Subject
  # @abstract
  def request
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# Реальный Субъект содержит некоторую базовую бизнес-логику. Как правило,
# Реальные Субъекты способны выполнять некоторую полезную работу, которая к тому
# же может быть очень медленной или точной – например, коррекция входных данных.
# Заместитель может решить эти задачи без каких-либо изменений в коде Реального
# Субъекта.
class RealSubject < Subject
  def request
    puts 'RealSubject: Handling request.'
  end
end

# Интерфейс Заместителя идентичен интерфейсу Реального Субъекта.
class Proxy < Subject
  # @param [RealSubject] real_subject
  def initialize(real_subject)
    @real_subject = real_subject
  end

  # Наиболее распространёнными областями применения паттерна Заместитель
  # являются ленивая загрузка, кэширование, контроль доступа, ведение журнала и
  # т.д. Заместитель может выполнить одну из этих задач, а затем, в зависимости
  # от результата, передать выполнение одноимённому методу в связанном объекте
  # класса Реального Субъекта.
  def request
    return unless check_access

    @real_subject.request
    log_access
  end

  # @return [Boolean]
  def check_access
    puts 'Proxy: Checking access prior to firing a real request.'
    true
  end

  def log_access
    print 'Proxy: Logging the time of request.'
  end
end

# Клиентский код должен работать со всеми объектами (как с реальными, так и
# заместителями) через интерфейс Субъекта, чтобы поддерживать как реальные
# субъекты, так и заместителей. В реальной жизни, однако, клиенты в основном
# работают с реальными субъектами напрямую. В этом случае, для более простой
# реализации паттерна, можно расширить заместителя из класса реального субъекта.
#
# @param [Subject] subject
def client_code(subject)
  # ...

  subject.request

  # ...
end

puts 'Client: Executing the client code with a real subject:'
real_subject = RealSubject.new
client_code(real_subject)

puts "\n"

puts 'Client: Executing the same client code with a proxy:'
proxy = Proxy.new(real_subject)
client_code(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.

Заместитель на других языках программирования

Заместитель на C# Заместитель на C++ Заместитель на Go Заместитель на Java Заместитель на PHP Заместитель на Python Заместитель на Rust Заместитель на Swift Заместитель на TypeScript