The Proxy pattern provides a stand-in for another object, allowing you to control access to it. Proxies often add behavior like logging, access control, or lazy initialization—without modifying the original object.
Sometimes you don’t want direct access to an object. It might be expensive to create, live on a remote server, or require authorization. The Proxy pattern introduces a middle layer that can delay creation, enforce rules, or enhance functionality while keeping the core object unchanged.
Use this pattern when:
Common types of proxies include:
Avoid this pattern if:
The Proxy and the original object (the “real subject”) implement the same interface. The client interacts with the Proxy, which can perform checks or add logic before passing the request to the real object.
A security guard at a concert checks your ticket before letting you in. You don’t talk directly to the performers—the guard (proxy) manages access. They might also record who enters. This is similar to a software proxy managing access and logging requests.
class Subject:
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 before forwarding request...")
return True
def log_access(self) -> None:
print("Proxy: Logging the time of request.")
if __name__ == "__main__":
real_subject = RealSubject()
proxy = Proxy(real_subject)
print("Client: Executing request through the proxy:")
proxy.request()
Client: Executing request through the proxy:
Proxy: Checking access before forwarding request...
RealSubject: Handling request.
Proxy: Logging the time of request.
See the full Python implementation here: Proxy Pattern on GitHub