As a material for learning GoF design patterns, the book "Introduction to Design Patterns Learned in the Augmented and Revised Java Language" seems to be helpful. However, since the examples taken up are based on JAVA, I tried the same practice in Python to deepen my understanding.
The Proxy pattern is a type of design pattern in programming. A Proxy is, broadly speaking, a class that acts as an interface to something else. The "other thing" can be anything, such as a network connection, a large object in memory, or some resource that is costly or impossible to duplicate. A well-known example of the Proxy pattern is a pointer object with reference counting. In situations where multiple copies of complex objects are required, adding a Flyweight pattern to the Proxy pattern can reduce memory usage. Normally, you create only one instance of a complex object and multiple proxy objects. Those proxy objects contain only references to complex objects. Operations on the proxy are forwarded to the original object. When all proxy objects are destroyed, the memory used by the referenced complex object is also freed.
UML class and sequence diagram UML class diagram (The above is quoted from Wikipedia)
I would like to actually run a sample program that utilizes the Proxy pattern and check the following behavior.
--First, accept "Alice" as a printer agent --Prepare the printer so that it can be used (time required is about 10 seconds) --Actually, use the printer to perform the following printout process "** Nice to meet you ". --Next, accept "Bob" as a printer agent --Actually, use the printer to perform the following printout process " Hello, World **".
$ python Main.py
The name of the Printer agent is now(Alice)is
Printer instance(Alice)Is being created..........Done
===Printer user(Alice) ===
Nice to meet you
The name of the Printer agent is now(Bob)is
===Printer user(Bob) ===
Hello, World
The confirmation point here is that the Printer instance (xxx) is being created .......... Done "</ font> is displayed only once. It is a point. In the actual sample program, Singleton pattern is used so that an instance of a complex object can be created only once.
Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/Proxy
--Directory structure
.
├── Main.py
└── proxy
├── __init__.py
└── printer_proxy.py
Defines an interface for identifying the Proxy
role and the RealSubject
role.
Thanks to the Subject
role, the Client
role does not need to be aware of the difference between the Proxy
and RealProxy
roles.
In the sample program, the Printable
class serves this role.
proxy/printer_proxy.py
class Printable(metaclass=ABCMeta):
@abstractmethod
def setPrinterName(self, name):
pass
@abstractmethod
def getPrinterName(self):
pass
@abstractmethod
def myPrint(self, string):
pass
The Proxy
role handles requests from the Client
role as much as possible.
If you can't handle it by yourself, the Proxy
role will leave the job to the RealSubject
role.
The Proxy
role will generate the RealSubject
role after you really need the RealSubject
role.
The Proxy
role implements the interface defined by the Subject
role.
In the sample program, the PrinterProxy
class serves this role.
proxy/printer_proxy.py
class PrinterProxy(Printable):
def __init__(self, name):
self.__name = name
self.__real = None
def setPrinterName(self, name):
self.__name = name
def getPrinterName(self):
return self.__name
def myPrint(self, string):
self.__real = Printer.getPrinter(self.__name)
self.__real.myPrint(string)
The role of "Real Subject" of "Person" appears when the role of
Proxyof" Proxy "is out of control. Like the
Proxy role, this role also implements the interface defined by the
Subjectrole. In the sample program, the
Printer` class serves this role.
proxy/printer_proxy.py
class Printer(Printable):
@classmethod
def getPrinter(cls, name):
if not hasattr(cls, "_instance"):
cls._instance = cls(name)
else:
cls._instance.__name = name
return cls._instance
def __init__(self, name):
self.__name = name
self.__heavyJob('Printer instance({})Is being created'.format(self.__name))
def setPrinterName(self, name):
self.__name = name
def getPrinterName(self):
return self.__name
def myPrint(self, string):
print('===Printer user({}) ==='.format(self.__name))
print(string)
print("")
def __heavyJob(self, msg):
print(msg, end='')
for _ in range(10):
time.sleep(1)
print('.', end='')
print('Done')
It is a role that uses the Proxy
role.
In the sample program, the startMain
method serves this role.
Main.py
from proxy.printer_proxy import PrinterProxy
def startMain():
p = PrinterProxy("Alice")
print("The name of the Printer agent is now({})is".format(p.getPrinterName()))
p.myPrint("Nice to meet you")
p.setPrinterName("Bob")
print("The name of the Printer agent is now({})is".format(p.getPrinterName()))
p.myPrint("Hello, World")
if __name__ == '__main__':
startMain()
-[Finishing "Introduction to Design Patterns Learned in Java Language" (Not)](https://medium.com/since-i-want-to-start-blog-that-looks-like-men-do/java Introduction to Design Patterns Learned in Languages-Finishing-No-2cc9b34a30b2) -[Qiita article "Design Pattern #Proxy" (https://qiita.com/nirperm/items/cb200058edb935adb26c)
Recommended Posts