Заместитель на Python
Заместитель — это объект, который выступает прослойкой между клиентом и реальным сервисным объектом. Заместитель получает вызовы от клиента, выполняет свою функцию (контроль доступа, кеширование, изменение запроса и прочее), а затем передаёт вызов сервисному объекту.
Заместитель имеет тот же интерфейс, что и реальный объект, поэтому для клиента нет разницы — работать через заместителя или напрямую.
Сложность:
Популярность:
Применимость: Паттерн Заместитель применяется в Python коде тогда, когда надо заменить настоящий объект его суррогатом, причём незаметно для клиентов настоящего объекта. Это позволит выполнить какие-то добавочные поведения до или после основного поведения настоящего объекта.
Признаки применения паттерна: Класс заместителя чаще всего делегирует всю настоящую работу своему реальному объекту. Заместители часто сами следят за жизненным циклом своего реального объекта.
Концептуальный пример
Этот пример показывает структуру паттерна Заместитель, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.
main.py: Пример структуры паттерна
from abc import ABC, abstractmethod class Subject(ABC): """ Интерфейс Субъекта объявляет общие операции как для Реального Субъекта, так и для Заместителя. Пока клиент работает с Реальным Субъектом, используя этот интерфейс, вы сможете передать ему заместителя вместо реального субъекта. """ @abstractmethod def request(self) -> None: pass class RealSubject(Subject): """ Реальный Субъект содержит некоторую базовую бизнес-логику. Как правило, Реальные Субъекты способны выполнять некоторую полезную работу, которая к тому же может быть очень медленной или точной – например, коррекция входных данных. Заместитель может решить эти задачи без каких-либо изменений в коде Реального Субъекта. """ def request(self) -> None: print("RealSubject: Handling request.") class Proxy(Subject): """ Интерфейс Заместителя идентичен интерфейсу Реального Субъекта. """ def __init__(self, real_subject: RealSubject) -> None: self._real_subject = real_subject def request(self) -> None: """ Наиболее распространёнными областями применения паттерна Заместитель являются ленивая загрузка, кэширование, контроль доступа, ведение журнала и т.д. Заместитель может выполнить одну из этих задач, а затем, в зависимости от результата, передать выполнение одноимённому методу в связанном объекте класса Реального Субъекта. """ if self.check_access(): self._real_subject.request() self.log_access() def check_access(self) -> bool: print("Proxy: Checking access prior to firing a real request.") return True def log_access(self) -> None: print("Proxy: Logging the time of request.", end="") def client_code(subject: Subject) -> None: """ Клиентский код должен работать со всеми объектами (как с реальными, так и заместителями) через интерфейс Субъекта, чтобы поддерживать как реальные субъекты, так и заместителей. В реальной жизни, однако, клиенты в основном работают с реальными субъектами напрямую. В этом случае, для более простой реализации паттерна, можно расширить заместителя из класса реального субъекта. """ # ... subject.request() # ... if __name__ == "__main__": print("Client: Executing the client code with a real subject:") real_subject = RealSubject() client_code(real_subject) print("") print("Client: Executing the same client code with a proxy:") proxy = Proxy(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.