nono blog
楽しい人生を送りたい!
ITスキル

pythonプログラム デザインパターン(Prototype)

Prototypeパターンとは

(概要)
Prototpyeとは、原型や試作品を表す。
Prototpyeパターンでは、あるインスタンスから同じクラスのインスタンスのクローンを
作成するデザインパターンである。

(目的)
あるインスタンスから同じインスタンスのコピーを作成して、複製作業を簡単にできるようにする。

(仕組み)
インターフェース(抽象クラス)にて、複製するオブジェクトの骨組みを作成する
複製したいクラスはインターフェースを継承する
複製したい状態でクラスを登録して、必要に応じて複製を作成する。

(構成要素)
Prototype : 複製するオブジェクトの構成要素(設計図)を定義するインターフェース
ConcretePrototype : Prototypeを具体化したクラス(複製作成する)
Manager : ConcretePrototypeを登録し複製を作成するクラス
 Copyモジュール(pythonの標準モジュール):オブジェクトのコピーを作成する関数(deepcopy)を提供

pythonサンプルコード

prototypeパターンのpythonサンプルコード

# prototype.py
from abc import ABC, abstractmethod
from copy import deepcopy


class Prototype(ABC):

    @abstractmethod
    def use(self, msg):
        pass

    @abstractmethod
    def _clone(self):
        pass


class MessageBox(Prototype):
    """ Prototypeを継承した、ConcretePrototype """

    def __init__(self, decoration_char):
        self.__decoration_char = decoration_char

    def use(self, msg):
        str_msg = str(msg)
        print(self.__decoration_char * (len(str_msg) + 4))
        print(self.__decoration_char + ' ' + str_msg + self.__decoration_char)
        print(self.__decoration_char * (len(str_msg) + 4))

    def _clone(self):
        print('Copy and Create MessageBox Clone')
        return deepcopy(self)

    @property
    def decoration_char(self):
        return self.__decoration_char

    @decoration_char.setter
    def decoration_char(self, decoration_char):
        self.__decoration_char = decoration_char


class UnderLinePen(Prototype):

    def __init__(self, underline_char):
        self.__underline_char = underline_char

    def use(self, msg):
        str_msg = str(msg)
        print(str_msg)
        print(self.__underline_char * len(str_msg))

    def _clone(self):
        print('Copy and Create UnderlinePen Clone')
        return deepcopy(self)

    @property
    def underline_char(self):
        return self.__underline_char

    @underline_char.setter
    def underline_char(self, underline_char):
        self.__underline_char = underline_char


class Manager(object):

    def __init__(self):
        self.__products = {}

    def register(self, name, prototype: Prototype):
        self.__products[name] = deepcopy(prototype)

    def create_product(self, name):
        # 辞書型のproductsから nameキーに一致するproductオブジェクトを取得
        product = self.__products.get(name)
        # 取得したオブジェクトのクローンメソッドを呼び出してクローンを作成する
        return product._clone()


if __name__ == '__main__':

    # Managerをそのままインスタンス化する
    manager = Manager()

    # 各インスタンスの初期設定を作成
    m_box = MessageBox('*')
    m_box.use('Hello Box')
    u_pen = UnderLinePen('-')
    u_pen.use('Hello Pen')

    # managerに、初期設定の各インスタンスを名前をつけて登録する
    manager.register('message_box', m_box)
    manager.register('underline_pen', u_pen)

    print('')
    # Managerを用いて新しいインスタンスを作成すると、初期設定のクローンで新しいインスタンスが作成できる。
    new_m_box = manager.create_product('message_box')
    new_m_box.use('New Box')
    new_u_pen = manager.create_product('underline_pen')
    new_u_pen.use('New Pen')

    print('')
    # 作成された個別のm_boxの設定を変えた場合の影響。manager登録時の設定には影響しない。
    m_box.decoration_char = '-'
    m_box.use('Hello m_box2')
    m_box_clone = manager.create_product('message_box')
    m_box_clone.use('Hello m_box_clone') #初期設定の*のまま