"필요해지면 만들기"
(1) Subject(주체)의 역할 : 프록시와 RealSubject의 역할을 동일시하기 위한 인터페이스를 결정한다.
(2) Proxy(대리인)의 역할 : 클라이언트의 요구를 할 수 있는 만큼 처리한다. 그러나 처리할 수 없으면 RealSubject에게 처리를 맡긴다.
(3) RealSubject(실제의 주체 - 본인)의 역할 : 프록시가 감당할 수 없는 일이 발생했을 때 처리한다.
(4) Client(의뢰인)의 역할 : 프록시 패턴을 사용하는 역할이다.


주요 사용처는 은행의 DB등이 있다. 이때, 클라이언트가 직접 접근하지 않고 프록시에서 일을 대신 처리한다.
- 우주를 탐사하는 코드를 프록시 패턴으로 만들어보자.
해당 코드를 만들기 전에 UML을 그려보면 다음과 같다.

그리고 등장인물을 나누면 다음과 같다.

자 이제 코드를 만들어 보자.
from abc import ABCMeta, abstractmethod
import time
class Printable(metaclass=ABCMeta):
def __init__(self, name):
self.name = name
@abstractmethod
def setPrinterName(self, name):
pass
@abstractmethod
def getPrinterName(self):
pass
@abstractmethod
def print(self, msg):
pass
class PrinterProxy(Printable):
def __init__(self, name):
self.name = name
self.real = None # 실제 Printer 객체는 초기에 None
def setPrinterName(self, name):
if self.real is not None:
self.real.setPrinterName(name)
self.name = name # 프록시가 이름을 기억
def getPrinterName(self):
return self.name
def realize(self): # 실제 Printer 객체 생성
if self.real is None:
self.real = Printer(self.name)
def print(self, msg):
self.realize() # 필요한 경우 실제 Printer 객체 생성
self.real.print(msg) # 실제 Printer 객체에 작업 위임
class Printer(Printable):
def __init__(self, name):
self.heavyJob("Printer 인스턴스(" + name + ") 생성 중") # 무거운 작업 시뮬레이션
self.name = name
def setPrinterName(self, name):
self.name = name
def getPrinterName(self):
return self.name
def print(self, msg):
print(self.name + ":", msg)
def heavyJob(self, msg): # 무거운 작업 시뮬레이션
print(msg)
for i in range(5):
time.sleep(1)
print("완료")
# 클라이언트 코드 (이미지에 있는 코드 포함)
p = PrinterProxy("보스토크")
print("현재 이름은 " + p.getPrinterName() + "입니다.")
p.setPrinterName("머큐리")
print("현재 이름은 " + p.getPrinterName() + "입니다.")
p.print("hello, How are you?")
p.print("Do you hear me?")
p.setPrinterName("아폴로")
print("현재 이름은 " + p.getPrinterName() + "입니다.")
p.print("We successfully arrived the moon.")
Proxy와 Real을 분리할 필요가 있을까?