diff --git a/structural/proxy/main.py b/structural/proxy/main.py new file mode 100644 index 0000000..424a68f --- /dev/null +++ b/structural/proxy/main.py @@ -0,0 +1,25 @@ +from structural.proxy.proxy import Proxy +from structural.proxy.real_subject import RealSubject +from structural.proxy.subject import Subject + + +def client_code(subject: Subject) -> None: + """ + The client code is supposed to work with all objects (both subjects and + proxies) via the Subject interface in order to support both real subjects + and proxies. In real life, however, clients mostly work with their real + subjects directly. In this case, to implement the pattern more easily, you + can extend your proxy from the real subject's class. + """ + + 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) diff --git a/structural/proxy/proxy.py b/structural/proxy/proxy.py new file mode 100644 index 0000000..3e0ed26 --- /dev/null +++ b/structural/proxy/proxy.py @@ -0,0 +1,28 @@ +from structural.proxy.real_subject import RealSubject +from structural.proxy.subject import Subject + + +class Proxy(Subject): + """The Proxy has an interface identical to the RealSubject.""" + + def __init__(self, real_subject: RealSubject) -> None: + self._real_subject = real_subject + + def request(self) -> None: + """ + The most common applications of the Proxy pattern are lazy loading, + caching, controlling the access, logging, etc. A Proxy can perform one + of these things and then, depending on the result, pass the execution to + the same method in a linked RealSubject object. + """ + + 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="") diff --git a/structural/proxy/real_subject.py b/structural/proxy/real_subject.py new file mode 100644 index 0000000..d558f1d --- /dev/null +++ b/structural/proxy/real_subject.py @@ -0,0 +1,13 @@ +from structural.proxy.subject import Subject + + +class RealSubject(Subject): + """ + The RealSubject contains some core business logic. Usually, RealSubjects are + capable of doing some useful work which may also be very slow or sensitive - + e.g. correcting input data. A Proxy can solve these issues without any + changes to the RealSubject's code. + """ + + def request(self) -> None: + print("RealSubject: handling request.") diff --git a/structural/proxy/subject.py b/structural/proxy/subject.py new file mode 100644 index 0000000..33a4634 --- /dev/null +++ b/structural/proxy/subject.py @@ -0,0 +1,13 @@ +from abc import abstractmethod, ABC + + +class Subject(ABC): + """ + The Subject interface declares common operations for both RealSubject and + the Proxy. As long as the client works with RealSubject using this + interface, you'll be able to pass it a proxy instead of a real subject. + """ + + @abstractmethod + def request(self) -> None: + pass