DEV Community

Cover image for Design Pattern in Python (5): Proxy Pattern
Z. QIU
Z. QIU

Posted on

Design Pattern in Python (5): Proxy Pattern

Introduction

Proxy Pattern provides a surrogate or placeholder for another object to control access to it. In Proxy Pattern, we create object (proxy) having original object (real) to interface its functionality to outer world.

Proxy Pattern is classified into structural patterns category.
Alt Text

There are three roles in Proxy Pattern :

  1. Subject: Interface class that defines operations and tasks
  2. Real Subject: concrete class that DO REAL operations and tasks
  3. Proxy Subject: Proxy class that performs the REAL operations and tasks on behalf of a Real Subject.

Sample structure of Proxy pattern:
Alt Text

Exercise of my anecdote

Once upon a time, my girlfriend and I were separated in two different countries for several months. Then I wanted to give a gift to her for her upcoming birthday. So I bought a gift on line and sent it to one of our common friends. This friend then handed it to my girlfriend along with a card with my message printed on it.

So I would like to do a simple exercise to simulate this anecdote of mine. For the sake of privacy, I use Romeo and Julia to replace the real names in this story :D.

Simulation

Now I start to code for simulating the following scenario: Romeo gave rose directly to Julia, and he asked Jack to give a chocolate to Julia in his behalf.

Firstly define classes of the three roles of Proxy Pattern.

from abc import ABCMeta, abstractmethod

class Subject(metaclass=ABCMeta):
    """ Subject class """

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name

    @abstractmethod
    def request(self, content = ''):
        pass


class RealSubject(Subject):
    """RealSubject class"""

    def request(self, content):
        print("RealSubject todo something...")


class ProxySubject(Subject):
    """ ProxySubject Class"""

    def __init__(self, name, subject):
        super().__init__(name)
        self._realSubject = subject

    def request(self, content = ''):
        self.preRequest()
        if(self._realSubject is not None):
            self._realSubject.request(content)
        self.afterRequest()

    def preRequest(self):
        print("preRequest")

    def afterRequest(self):
        print("afterRequest")

class RomeoGiving(Subject):
    """Romeo gives gift"""

    def __init__(self, name, wishMsg, receiver):
        super().__init__(name)
        self.__message = wishMsg
        self.__receiver = receiver

    def getMsg(self):
        return self.__message

    def getReceiver(self):
        return self.__receiver

    def request(self, content):
        print("  {} sends gift to {} with a wish Message:\"{}\"" .format(self.getName(), self.getReceiver(), self.getMsg()))
        print("  Gift is {}".format( str(content)) )


class JackGiving(ProxySubject):
    """Jack gives gift instead"""

    def __init__(self, name, GivingTask):
        super().__init__(name, GivingTask)

    def preRequest(self):
        print(" [Proxy] {} saying: I give you the gift on behalf of {}".format(self.getName(), self._realSubject.getName() ))

    def afterRequest(self):
        print(" [Proxy] {} saying: I have given gift to {} on behalf of {}" .format(self.getName(), self._realSubject.getReceiver(), self._realSubject.getName()  ))

Enter fullscreen mode Exit fullscreen mode

Now launch the simulation:


if __name__ == '__main__':

    print("=================" )
    Romeo = RomeoGiving("Romeo", "I loved you, I love you and I will love you forever.", "Julia")
    print("Romeo gives gift: ")
    Romeo.request("Rose")

    print("=================" )

    print("Jack gives gift instead")
    Jack = JackGiving("Jack", Romeo)
    Jack.request("Chocolate")

Enter fullscreen mode Exit fullscreen mode

Simulation execution output:
Alt Text

Top comments (0)