๋ฐ์ํ
Prototype Pattern
๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ๋ฏธ๋ฆฌ ์ ์๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ณต์ (clone)ํ์ฌ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋๋ค
- ์๋์ ๊ฒฝ์ฐ ํด๋์ค๋ก๋ถํฐ ์ธ์คํด์ค๋ฅผ ๋ง๋๋ ๊ฒ์ด ์๋๋ผ ์ธ์คํด์ค๋ฅผ ๋ณต์ฌํด์ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ๋ง๋๋๊ฒ์ด ์ข์ต๋๋ค.
- ์ข ๋ฅ๊ฐ ๋๋ฌด ๋ง์์ ํด๋์ค๋ก ์ ๋ฆฌ๋์ง ์๋ ๊ฒฝ์ฐ
- ํด๋์ค๋ก๋ถํฐ ์ธ์คํด์ค ์์ฑ์ด ์ด๋ ค์ด ๊ฒฝ์ฐ
- framework ์ ์์ฑํ๋ ์ธ์คํด์ค๋ฅผ ๋ถ๋ฆฌํ๊ณ ์ถ์ ๊ฒฝ์ฐ
์ฅ์
- ๊ฐ์ฒด ์์ฑ ๋น์ฉ ์ ๊ฐ: ๋ณต์ (clone) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฏ๋ก, ๊ฐ์ฒด๋ฅผ ์ฒ์๋ถํฐ ์์ฑํ๋ ๊ฒ๋ณด๋ค ๋น์ฉ์ด ์ ๊ฒ ๋ญ๋๋ค.
- ๊ฐ์ฒด ์ด๊ธฐํ์ ๋จ์ํ: ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ด๊ธฐํํ๋ ๊ณผ์ ์ด ๋ณต์กํ ๊ฒฝ์ฐ, ๋ฏธ๋ฆฌ ์ด๊ธฐํ๋ ๊ฐ์ฒด๋ฅผ ๋ณต์ ํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ๋์ ์ธ ๊ฐ์ฒด ์์ฑ: ๋ฐํ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์์ ํ ์ ์์ต๋๋ค.
๋จ์
- ๊น์ ๋ณต์ฌ์ ์์ ๋ณต์ฌ: ๊ฐ์ฒด๋ฅผ ๋ณต์ ํ ๋, ๊น์ ๋ณต์ฌ์ ์์ ๋ณต์ฌ์ ๊ฐ๋ ์ ๋ช ํํ ์ดํดํ๊ณ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์๋ชป๋ ๋ณต์ ๋ฐฉ์์ ์์์น ๋ชปํ ๋์์ ์ด๋ํ ์ ์์ต๋๋ค.
- ๋ณต์ ์ ๋ณต์ก์ฑ: ๊ฐ์ฒด ๋ด๋ถ์ ์ฐธ์กฐํ ํ๋๊ฐ ๋ง์ ๊ฒฝ์ฐ, ๋ณต์ ๋ฉ์๋์ ๊ตฌํ์ด ๋ณต์กํด์ง ์ ์์ต๋๋ค.
Example
- ๋ด๋ถ property๋ก ๋, ์ฝ, ๋ชธ, ๊ผฌ๋ฆฌ ์๊น, ์ด๋ฆ์ ์ง์ ํ ์ ์๋ ๊ณ ์์ด Class
class Cat:
def __init__(self):
self.color = None
self.eye_color = None
self.nose_color = None
self.tail_color = None
self.name = None
- ๋, ์ฝ, ๋ชธ, ๊ผฌ๋ฆฌ ์๊น ๋ชจ๋ white์ด๋ฉฐ ์ด๋ฆ์ kitty์ธ ๊ณ ์์ด
kitty = Cat()
kitty.color = "white"
kitty.eye_color = "white"
kitty.nose_color = "white"
kitty.tail_color = "white"
kitty.name = "Kitty"
- ๋, ์ฝ, ๋ชธ, ๊ผฌ๋ฆฌ ์๊น ๋ชจ๋ white์ด๋ฉฐ ์ด๋ฆ์ nabi์ธ ๊ณ ์์ด
nabi = Cat()
nabi.color = "white"
nabi.eye_color = "white"
nabi.nose_color = "white"
nabi.tail_color = "white"
nabi.name = "Nabi"
- ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๊ฐ ์ฃผ์๊น๊ฒ ๋ด์ผํ ์ ์ด ์์ต๋๋ค.
- ๋, ์ฝ, ๋ชธ, ๊ผฌ๋ฆฌ ์๊น ๋ชจ๋ ๋์ผํ๋ฉฐ ์ด๋ฆ๋ง ๋ค๋ฅธ ๊ณ ์์ด๋ฅผ ๋ง๋ค๊ธฐ ์ํด ๋ชจ๋ property๋ฅผ ํ๋์ฉ ๋ฐ๋ก ์ง์ ํ๋ ๊ฒ์ ๋นํจ์จ์ ์ ๋๋ค
- ๊ณ ์์ด๋ฅผ ๋ณต์ ํด์ ๋ง๋ค์ด๋ผ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋ค๋ฉด ๋ ์ฝ๊ฒ ๋ ๋ฒ์งธ ๊ณ ์์ด nabi๋ฅผ ๋ง๋ค ์ ์์๊ฒ ์ ๋๋ค.
- ํ๋ฒ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
import copy
class Cat:
def __init__(self):
self.color = None
self.eye_color = None
self.nose_color = None
self.tail_color = None
self.name = None
def clone(self):
return copy.deepcopy(self)
kitty = Cat()
kitty.color = "white"
kitty.eye_color = "white"
kitty.nose_color = "white"
kitty.tail_color = "white"
kitty.name = "Kitty"
nabi = kitty.clone()
nabi.name = "Nabi"
- ์ ์ํ Cat class ์์ ๋์ผํ ๊ณ ์์ด๋ฅผ ์์ฑํด์ฃผ๋ Clone ๊ธฐ๋ฅ์ ํตํด ๋ ๋ฒ์งธ ๊ณ ์์ด property๋ฅผ ํ๋์ฉ ์ง์ ํ ํ์์์ด cloneํ ๋ค์ nabi์ด๋ฆ๋ง ์ง์ ํ๋ฉด ๋ฉ๋๋ค.
- kitty → clone์ ํตํด nabi ๋ฅผ ๋ณต์ ํฉ๋๋ค.
- ๊ทผ๋ฐ, nabi = kitty ์์ผ๋ก ๋ณต์ฌ๋ง ํ ๊ฒฝ์ฐ๋?
- Reference ๊ธฐ๋ฐ ์ธ์ด๋ Object๊ฐ Reference๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ ์ด์ ๊ฐ์ด ๋ณต์ฌ๋ง ํ ๊ฒฝ์ฐ, ํ๋์ Object๋ฅผ ๊ฐ๋ฆฌํค๋ Reference๊ฐ 2๊ฐ ์๊ธธ ๋ฟ์ ๋๋ค.
- ๋ฐ๋ผ์ deepcopy๋ฅผ ํตํด ๊ณ ์์ด ์ ์ฒด๋ฅผ ๋ณต์ฌํด ์ค์ผ ํฉ๋๋ค.
Prototype design pattern์ ์๋๋ object๊ฐ copy๋๊ธฐ ์ ๊น์ง ์ํ๋ฅผ prototype์ผ๋ก ๊ฐ์ง๊ณ ์์ผ๋ผ๋ ๊ฒ์ ๋๋ค.
import copy
class Cat:
def __init__(self):
self.color = None
self.eye_color = None
self.nose_color = None
self.tail_color = None
self.name = None
def clone(self):
return copy.deepcopy(self)
class BlackCat(Cat):
def __init__(self):
super().__init__()
self.color = 'black'
class WhiteCat(Cat):
def __init__(self):
super().__init__()
self.color = 'white'
- ์ฌ๊ธฐ์ Cat class๋ Base class์ ๋๋ค.
- BlackCat, WhiteCat class๋ Cat class๋ฅผ ์์ ๋ฐ์์ ๊ณ ์์ด ๋ชธ ์๊น๋ง ๊ฐ๊ฐ black, white๋ก ์ด๊ธฐํ ํฉ๋๋ค.
black_cat = BlackCat()
- black_cat์ ๋ชธ ์๊น๋ง ์ง์ ๋์ด ์๋ ์ํ์ ๋๋ค.
- ๊ทธ ๋ค์ ์ฝ, ๊ผฌ๋ฆฌ ์์ ์ง์ ํฉ๋๋ค.
์ด๋ ๊ฒ ๋ง๋ค์ด์ง object๋ฅผ prototype์ผ๋ก ์ฌ์ฉํด์ kitty & nabi๋ฅผ ๋ง๋ญ๋๋ค.
kitty = black_cat.clone()
kitty.eye_color = "white"
kitty.name = 'kitty'
nabi = black_cat.clone()
nabi.eye_color = "blue"
nabi.name = 'nabi'
- ์ฆ, kitty๋ black_cat์ cloneํ, ๋ ์๊น, ์ด๋ฆ์ ์ง์ ํด์ ๋ฏธ์์ฑ๋ prototpye object๋ฅผ ์ฌ์ฉํด์ ์ํ๋ kitty object๋ฅผ ์ฝ๊ฒ ๋ง๋ค์ด๋ ๋๋ค. (nabi ๋ํ ๋์ผ)
์ค๊ฐ ๋จ๊ณ์ object๋ฅผ prototype์ผ๋ก ๋ง๋ค๊ณ ์ด๋ฅผ deepcopyํด์ object๋ฅผ ๋ง๋ค์ด๊ฐ๋ ๋์์ธ ํจํด์ ๋๋ค.
Prototype์ ํต์ฌ ๊ฐ๋
- Prototype(์ํ)์ ์ญํ
- Prototype์ ์ธ์คํด์ค๋ฅผ ๋ณต์ฌํ์ฌ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
- ConcretePrototpye (๊ตฌ์ฒด์ ์ธ ์ํ)์ ์ญํ
- ConcretePrototpye์ ์ธ์คํด์ค๋ฅผ ๋ณต์ฌํด์ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ๋ง๋๋ ๋ฉ์๋๋ฅผ ๊ธธ์ ๋ก ๊ตฌํํฉ๋๋ค.
- Client(์ด์ฉ์)์ ์ญํ
- Client๋ ์ธ์คํด์ค๋ฅผ ๋ณต์ฌํ๋ ๋ฉ์๋๋ฅผ ์ด์ฉํด์ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ๋ง๋ญ๋๋ค.
Example
# prototype
from abc import *
class Product(metaclass=ABCMeta):
@abstractmethod
def use(self):
pass
@abstractmethod
def clone(self):
pass
# Concrete
class UnderlinePen(Product):
def use(self, s:str)
n = len(s)
print(s)
for i in range(n):
print("~", end="")
print()
def clone(self):
return copy.deepcopy(self)
# Concrete
class MessageBox(Product):
def _init_(self, deco:str):
self.deco = deco
def use(self, s:str):
n = len(s) + 4
for i in range(n):
print(self.deco, end="")
print()
print(self.deco, s, self.deco)
for i in range(n):
print(self.deco, end="")
print()
def clone(self):
return copy.deepcopy(self)
# Manager
class Manager:
def _init_(self):
self.showcase = {"a":1}
def register(self, name:str, proto:Product):
self.showcase[name] = proto
def create(self, protoname:str):
p = self.showcase[protoname]
return p.clone()
# Client
manager = Manager()
m1 = MessageBox("*")
m2 = MessageBox("#")
p1 = UnderlinePen()
manager.register("msg", m1)
manager.register("msg#", m2)
manager.register("pen", p1)
msg1 = manager.create("msg")
msg2 = manager.create("msg#")
pen = manager.create("pen")
word = "hello"
msg1.use(word)
word = "world"
msg2.use(word)
pen.use(word)
๋ฐ์ํ
'๐บ๏ธ Design Pattern' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Design Pattern] Singleton Pattern - ์ฑ๊ธํค ํจํด & Metaclass (0) | 2024.05.21 |
---|---|
[Design Pattern] Builder Pattern - ๋น๋ ํจํด (0) | 2024.05.21 |
[Design Pattern] Abstract Factory Pattern - ์ถ์ ํฉํ ๋ฆฌ ํจํด (0) | 2024.04.08 |
[Design Pattern] Factory Method Pattern - ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด (0) | 2024.04.08 |
[Design Pattern] Factory Pattern - ํฉํ ๋ฆฌ ํจํด (0) | 2024.04.08 |