0
1

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.

Strategyパターン Python実装 メモ

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

Strategy パターンとは

  • 「戦略」(アルゴリズムなど)の切り替えや追加を簡単に行うためのデザインパターン。
  • 戦略処理を別クラスとして作成することで、戦略を変更したい場合に、利用する戦略クラスを変更するという方法で対応する。
  • メソッド中にアルゴリズムをべた書きするよりも柔軟でメンテナンスしやすい設計となる。

クラス図と用語

strategy_pattern.png

  • Strategy:特定の処理を抽象化したクラス(抽象戦略)
  • ConcreteStrategy : 具体的な処理を行うクラス(具体戦略)
  • Context:Strategyの利用者

サンプルプログラム

  • ID生成処理を行うAPIに適用する。
    • クエリパラメータの有無でID生成用Strategyを切り替える。

ディレクトリ構成

Project
│  app.py
│
│
L_ api
   │  __init__.py
   │
   ├─views
     │  sample.py
     │  __init__.py
     │
     L_ strategy
           L_  IDgenerator.py
           L_  IDStrategy.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コントローラ
    from flask import Flask, Blueprint, request
    import json
    from .strategy.IDStrategy import IDStrategy
    from .strategy.IDStrategy import FixedIDStrategy, RandomIDStrategy
    from .strategy.IDgenerator import IDgenerator
    
    # Routing Settings
    sample_router = Blueprint('sample_router', __name__)
    
    app = Flask(__name__)
    
    
    @sample_router.route("/sample",  methods=['GET'])
    def get():
    
        query = request.args.get('q')
        id = ""
        # クエリパラメータ未指定の場合、固定のIDを取得する
        if query is not None:
            generator = IDgenerator(FixedIDStrategy())
            id = generator.generateID()
        # クエリパラメータ指定ありの場合、ランダムのIDを取得する
        else:
            generator = IDgenerator(RandomIDStrategy())
            id = generator.generateID()
    
        res_body = {
            "id": id
        }
        return json.loads(json.dumps(res_body))
    
    
  • api/views/strategy/IDStrategy.py

    • Strategy:抽象、具体戦略(ランダム、固定ID生成)定義
    import random
    
    # ID生成処理を抽象化したクラス(抽象戦略 Strategy)
    class IDStrategy:
        def generateID(self):
            raise 'Abstract Method Called'
    
    
    # ランダム生成したIDを返却するクラス(具体戦略 ConcreteStrategy)
    class RandomIDStrategy(IDStrategy):
        def generateID(self):
            chars = '0123456789abcdefghijklmnopqrstuvwxyz'
            return ''.join([random.choice(chars) for _ in range(16)])
    
    
    # 固定IDを返却するクラス(具体戦略 ConcreteStrategy)
    class FixedIDStrategy(IDStrategy):
        def generateID(self):
            return '0123abcd4567efgh'
    
    
  • api/views/strategy/IDgenerator.py

    • Context:ID生成Strategyを呼び出す。
    # コンテキスト(Context):ストラテジーの利用者
    class IDgenerator:
        def __init__(self, IDStrategy):
            self.IDStrategy = IDStrategy
    
        def generateID(self):
            return self.IDStrategy.generateID()
    
    

動作確認

  • ランダムID生成戦略の呼び出し(クエリパラメータ指定なし)

    • リクエスト

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

      {
          "id": "1arh3j2jba8x2fix"
      }
      
  • 固定ID生成戦略の呼び出し(クエリパラメータ指定あり)

    • リクエスト

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

      {
          "id": "0123abcd4567efgh"
      }
      

参考情報

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?