0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Factory Methodパターン Python実装 メモ

Posted at
  • Pythonとデザインパターンの学習記録。今回はFactory Methodパターンについてメモする。

Factory Methodパターン とは

  • インスタンスの生成方法を親クラスで定義し、具体的な処理を子クラスで行う、デザインパターンの一つ。
  • 実際のインスタンス生成を子クラスに行わせることで、生成するインスタンスを柔軟に選択できるようにする。
    • 生成するインスタンスごとにファクトリ(下記Creator)を用意する。

クラス図と用語

factory_method.png

  • 抽象クラス
    • Creator:インスタンス生成クラス
    • Product:生成対象オブジェクト
  • 具象クラス:抽象クラスに対応するCreatorとProduct

サンプルプログラム

  • ID生成処理を行うAPIに適用する。

    • クエリパラメータの有無でID生成処理(複数文字種 or 1文字種)を切り替える。

      factory_method_code.png

ディレクトリ構成

Project
│  app.py
L_ api
   │  __init__.py
   │
   ├─views
     │  sample.py
     │  __init__.py
     │
     L_ factorymethod
      	 │  factory.py
      	 L_  __init__.py
    	 │
         L_ generatorfactory
			 L_  one_char_id_generator_factory.py
			 L_  random_id_generator_factory.py
			 L_  __init__.py

実装

  • app.py

    from api import app
    
    if __name__ == '__main__':
        app.run()
    
    
  • api/__init__.py

    from flask import Flask
    from .views.sample import sample_router
    
    
    def create_app():
    
        app = Flask(__name__)
    
        app.register_blueprint(sample_router, url_prefix='/api')
    
        return app
    
    
    app = create_app()
    
    
  • api/views/sample.py

    • APIコントローラ
  • クエリパラメータの有無でID生成方法を切り替える。

    from flask import Flask, Blueprint, request
    import json
    from .factorymethod.generatorfactory.one_char_id_generator_factory import OneCharIDGenratorFactory
    from .factorymethod.generatorfactory.random_id_generator_factory import RandomIDGenratorFactory
    
    # Routing Settings
    sample_router = Blueprint('sample_router', __name__)
    
    app = Flask(__name__)
    
    
    def generateID(factoryObject, length):
        generator = factoryObject.create(length)
        return generator.generate()
    
    
    @sample_router.route("/sample",  methods=['GET'])
    def get():
    
        query = request.args.get('q')
        id = ""
        if query is not None:
            id = generateID(OneCharIDGenratorFactory(), 5)
        else:
            id = generateID(RandomIDGenratorFactory(), 5)
    
        res_body = {
            "id": id
        }
        return json.loads(json.dumps(res_body))
    
  • api/views/factorymethod/factory.py

    • 抽象Creator、Product 定義
    from abc import ABCMeta, abstractmethod
    
    # Creator
    class Factory(metaclass=ABCMeta):
        def create(self, length):
            p = self.createGenerator(length)
            return p
    
        @abstractmethod
        def createGenerator(self, length):
            pass
    
    # Product
    class Generator(metaclass=ABCMeta):
        @abstractmethod
        def generate(self, length):
            pass
    
  • api/views/factorymethod/one_char_id_generator_factory.py

    • 具象Creator/Product
    • 文字種1のランダムIDを生成
    from api.views.factorymethod.factory import Factory, Generator
    import random
    
    
    class OneCharIDGenratorFactory(Factory):
        def __init__(self):
            self.length = 0
    
        def createGenerator(self, length):
            return OneCharIDGenerator(length)
    
    
    class OneCharIDGenerator(Generator):
        def __init__(self, length):
            self.length = length
            print("長さ:{0} の1文字種 IDを生成します。".format(self.length))
    
        def generate(self):
            chars = '0123456789abcdefghijklmnopqrstuvwxyz'
            v = random.choice(chars)
            id = ''.join([v for _ in range(self.length)])
            print("ID:{0} を生成しました。".format(id))
            return id
    
    
  • api/views/factorymethod/random_id_generator_factory.py

    • 具象Creator/Product
    • 複数文字種のランダムIDを生成
    from api.views.factorymethod.factory import Factory, Generator
    import random
    
    
    class RandomIDGenratorFactory(Factory):
        def __init__(self):
            self.length = 0
    
        def createGenerator(self, length):
            return RandomIDGenerator(length)
    
    
    class RandomIDGenerator(Generator):
        def __init__(self, length):
            self.length = length
            print("長さ:{0} のランダムIDを生成します。".format(self.length))
    
        def generate(self):
            chars = '0123456789abcdefghijklmnopqrstuvwxyz'
            id = ''.join([random.choice(chars) for _ in range(self.length)])
            print("ID:{0} を生成しました。".format(id))
            return id
    

動作確認

  • 複数文字種のランダムID生成(クエリパラメータ指定なし)

    • リクエスト

      GET /api/sample HTTP/1.1
      Host: localhost:5000
      
    • レスポンス

      {
          "id": "1arh3j2jba8x2fix"
      }
      
  • 1文字種のランダムID生成(クエリパラメータ指定あり)

    • リクエスト

      GET /api/sample?q=test HTTP/1.1
      Host: localhost:5000
      
    • レスポンス

      {
          "id": "nnnnn"
      }
      

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?