Design Pattern in Python (5): Proxy Pattern
Tags: proxy, design, python, architecture
Published: 2020-12-11 13:50:58

## 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](https://dev-to-uploads.s3.amazonaws.com/i/6793ysx0tt5ylohjs31o.PNG)


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](https://dev-to-uploads.s3.amazonaws.com/i/rzao87u5gvevysrd8eni.PNG)



## 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.

```python
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()  ))

```

Now launch the simulation:
```python

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

Simulation execution output:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/bjf6mjead7hz08i78w4y.PNG)