Thread

Proxy Pattern

The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. It acts as an intermediary between the client and the real object, providing additional functionality or controlling the access to the real object.

Empty image or helper icon

Proxy Pattern

Description

The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. It acts as an intermediary between the client and the real object, providing additional functionality or controlling the access to the real object. This pattern is useful in scenarios where access control is required, additional functionality needs to be added before or after accessing a real object, or a lightweight representation of a heavy object is needed. The Proxy Pattern adds a level of indirection between the client and the real object, allowing for added functionality without modifying the client code. However, it also introduces complexity and can potentially impact performance. The Proxy Pattern is related to the Decorator Pattern, which focuses on adding new behaviors to an object dynamically.

Proxy Pattern

Tool: Design Pattern Implementer

Created: 01/31/2024

Prompt

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.")

def client_code(subject: Subject) -> None:
    subject.request()

real_subject = RealSubject()
proxy = Proxy(real_subject)
client_code(proxy)

Design Pattern: Proxy Pattern

The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. It acts as an intermediary between the client and the real object, providing additional functionality or controlling the access to the real object.

Code Explanation

The given code snippet demonstrates the implementation of the Proxy Pattern. Here's how each component works:

  • Subject (Interface): Defines the common interface for the RealSubject and Proxy classes by declaring the request method.

  • RealSubject: Implements the Subject interface and defines its own implementation of the request method. It represents the real object that the client wants to access.

  • Proxy: Implements the Subject interface and maintains a reference to the RealSubject. It checks access permissions before allowing the RealSubject to handle the request. It performs additional tasks before and after calling the RealSubject.

  • client_code: Accepts a Subject object as a parameter and invokes its request method. The client interacts with the Subject object without directly accessing the RealSubject.

Code Template

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.")

def client_code(subject: Subject) -> None:
    subject.request()

real_subject = RealSubject()
proxy = Proxy(real_subject)
client_code(proxy)

Example Usage

In the given example, the RealSubject handles the request. However, before the RealSubject handles the request, the Proxy performs certain tasks, such as checking access permissions and logging the time of the request.

The client code interacts with the Subject object (in this case, the Proxy) without being aware of the RealSubject. This indirection provides flexibility and allows additional functionality to be added without modifying the client code.

Applicability

The Proxy Pattern is applicable in scenarios where:

  • Access control is required for a resource.
  • Additional functionality needs to be added before or after accessing a real object.
  • A lightweight representation of a heavy object is needed.

Benefits

  • Provides a level of indirection between the client and the real object.
  • Allows additional functionality to be added without modifying the client.
  • Provides a way to control access to the real object.
  • Can be used for remote communication, caching, logging, and other cross-cutting concerns.

Drawbacks

  • Adds complexity by introducing an extra layer between the client and the real object.
  • Can impact performance due to the overhead of the proxy.

Related Design Patterns

  • Decorator Pattern: Similar to the Proxy Pattern, both involve wrapping an object to add additional functionality. However, the Proxy Pattern focuses on controlling access to the real object, while the Decorator Pattern focuses on adding new behaviors to an object dynamically.

References

Proxy Pattern - Wikipedia