Featured image of post SP7 - Proxy - Learn Design Pattern From Simple Things

SP7 - Proxy - Learn Design Pattern From Simple Things

The boss wants the employees to focus on work and not get distracted by social media. So he decides to block some websites on the corporate network during working hours.

Proxy is a structural design pattern: šŸ–¤šŸ–¤šŸ–¤šŸ¤šŸ¤

What is Proxy?

Proxy is a design pattern that provides a surrogate or placeholder object for another object to control access to it. The proxy object has the same interface as the original object and delegates all the requests to it. The proxy can add some functionality or validation before or after accessing the original object.

A simple example of proxy is a company that restricts access to the free internet during working hours.

Proxy diagram

Why use Proxy?

Proxy is a design pattern that can be useful when you want to add some functionality or validation before accessing the original object.

Advantages:

  • It can enhance the security and performance of the original object by adding caching, logging, authorization, etc.
  • It can reduce the memory usage and loading time of the original object by creating it only when needed.
  • It can simplify the interface of the original object by hiding some complex details.

Disadvantages:

  • It can introduce some overhead and latency in the communication between the proxy and the original object.
  • It can be difficult to maintain consistency between the proxy and the original object if they are not updated together.

Question: I hate the Proxy, what are the alternatives?

Answer: You can merge the proxy logic into the original object, which may simplify the code but also increase the coupling and reduce the flexibility of the object. Or you can try using AOP, which also allows you to modify the behavior of the object without changing its code.

Proxy

When to use Proxy?

Question: When should I use Proxy?

Answer: You should use Proxy when you want to control or modify the behavior of another object without changing its code.

Input:

You have a class called FreeInternetAccess that grants access to anyone who wants to browse the free internet.

1
2
3
class FreeInternetAccess:
    def grant_access(self):
        print("Access granted. You can browse the free internet now!")

Expected Output:

You want to control when the access can be granted based on the current time. You expect to see the message “Sorry, access to the free internet is restricted during working hours!” when you try to access the free internet using the proxy during working hours.

1
2
3
4
5
6
7
8
# FreeInternetAccess
Access granted. You can browse the free internet now!

# CompanyProxyInternetAccess
# current time is 7:00 AM
#Access granted. You can browse the free internet now!
# current time is 9:00 AM
Sorry, access to the free internet is restricted during working hours!

How to implement Proxy?

Non-Proxy implementation:

You can skip Proxy and code normally. Or you can try AOP for fun. This code uses AOP to change a method’s behavior without changing its code. It defines an aspect function that limits free internet access by time. It uses aspectlib to apply the aspect function to a FreeInternetAccess object. The aspect function can run or skip the original method. But be careful, AOP may cause:

  • Bugs or side effects
  • Low readability and maintainability
  • High complexity and overhead
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import datetime
import aspectlib  # pip install aspectlib
from abc import ABC, abstractmethod


class InternetAccess(ABC):
    @abstractmethod
    def grant_access(self):
        pass


class FreeInternetAccess(InternetAccess):
    def grant_access(self):
        print("Access granted. You can browse the free internet now!")


@aspectlib.Aspect
def restrict_access(func, *args, **kwargs):
    current_time = datetime.datetime.now().time()
    start_time = datetime.time(8, 0)
    end_time = datetime.time(17, 30)
    if start_time <= current_time <= end_time:
        print("Sorry, access to the free internet is restricted during working hours!")
    else:
        yield aspectlib.Proceed


if __name__ == "__main__":
    # current time is 9:00 AM
    origin = FreeInternetAccess()
    origin.grant_access()
    try:
        aspectlib.weave(
            origin, restrict_access
        )  # apply the aspect to all methods of origin
        origin.grant_access()
    except StopIteration:
        pass

It looks cool, but it seems it’s not very friendly, right? Let’s see if proxy is more understandable.

Proxy Implementation:

A proxy implementation would be to use the CompanyProxyInternetAccess class as a wrapper for the FreeInternetAccess class and add some logic to check the current time before granting access. This would enforce the company policy and prevent unauthorized access during working hours, but it would also allow access during non-working hours.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import datetime
from abc import ABC, abstractmethod


class InternetAccess(ABC):
    @abstractmethod
    def grant_access(self):
        pass


class FreeInternetAccess(InternetAccess):
    def grant_access(self):
        print("Access granted. You can browse the free internet now!")


class CompanyProxyInternetAccess(InternetAccess):
    def __init__(self):
        self.free_internet_access = FreeInternetAccess()

    def grant_access(self):
        current_time = datetime.datetime.now().time()
        start_time = datetime.time(8, 0)
        end_time = datetime.time(17, 30)
        if start_time <= current_time <= end_time:
            print("Sorry, access to the free internet is restricted during working hours!")
        else:
            self.free_internet_access.grant_access()


if __name__ == "__main__":
    # current time is 9:00 AM
    origin = FreeInternetAccess()
    origin.grant_access()
    proxy = CompanyProxyInternetAccess()
    proxy.grant_access()

This code correlates and reflects the proxy design pattern by creating a proxy object that has the same interface as the original object and delegates all the requests to it. The proxy object also adds some functionality or validation before accessing the original object.

Proxy is a design pattern that can help you control or modify the behavior of another object without changing its code. It can also enhance the security and performance of the original object by adding caching, logging, authorization, etc.

Source Code

Made with the laziness šŸ¦„
by a busy guy