💡
Prototypeパターンを学ぶ【Python】
一言で言うと
生成済みのインスタンスから別のインスタンスを複製する。クラス名を指定せずにインスタンスを作りたい場合に使用できる。
コードサンプル
ディレクトリ構造
prototype
├── framework
│ ├── manager.py
│ └── product.py
├── main.py
├── message_box.py
└── under_line_pen.py
main.py
from framework.product import Product
from framework.manager import Manager
from message_box import MessageBox
from under_line_pen import UnderLinePen
def main():
manager: Manager = Manager()
upen: UnderLinePen = UnderLinePen('~')
mbox: MessageBox = MessageBox('*')
sbox: MessageBox = MessageBox('/')
manager.register('strong message', upen)
manager.register('warning box', mbox)
manager.register('slash box', sbox)
p1: Product = manager.create('strong message')
p1.use('Hello, world.')
p2: Product = manager.create('warning box')
p2.use('Hello, world.')
p3: Product = manager.create('slash box')
p3.use('Hello, world.')
if __name__ == '__main__':
main()
manager.py
from .product import Product
class Manager():
__showcase: dict = {}
def register(self, name: str, proto: Product) -> None:
self.__showcase[name] = proto
def create(self, protoname: str) -> Product:
p: Product = self.__showcase.get(protoname)
return p.createClone()
pruduct.py
from __future__ import annotations # 自分自身のクラスを返せるようにする
from abc import ABCMeta, abstractmethod
class Product(metaclass=ABCMeta):
@abstractmethod
def use(s: str) -> None:
pass
@abstractmethod
def createClone() -> Product:
pass
message_box.py
from framework.product import Product
from functools import reduce
from operator import add
from unicodedata import east_asian_width
import copy
class MessageBox(Product):
def __init__(self, decochar: str) -> None:
self.decochar: str = decochar
def use(self, s: str) -> None:
length: int = reduce(
# 全角2文字、半角1文字とする
add, [2 if east_asian_width(ch) in 'FWA' else 1 for ch in s]
)
for _ in range(length + 4):
print(self.decochar, end='')
print('')
print(f'{self.decochar} {s} {self.decochar}')
for _ in range(length + 4):
print(self.decochar, end='')
print('')
def createClone(self) -> Product:
return copy.deepcopy(self)
under_line_pen.py
from framework.product import Product
from functools import reduce
from operator import add
from unicodedata import east_asian_width
import copy
class UnderLinePen(Product):
def __init__(self, ulchar: str) -> None:
self.ulchar: str = ulchar
def use(self, s: str) -> None:
length: int = reduce(
# 全角2文字、半角1文字とする
add, [2 if east_asian_width(ch) in 'FWA' else 1 for ch in s]
)
print(f'"{s}"')
print(self.ulchar, end='')
for _ in range(length):
print(self.ulchar, end='')
print('')
def createClone(self) -> Product:
return copy.deepcopy(self)
Discussion