Python デザインパターン サンプルコード Chain of Responsibility
結城 浩「Java言語で学ぶデザインパターン入門」をPython化
Python3(3.11)で動くソースコード(.pyファイル .ipynbファイル)あります
「anaconda3」on .py「PyCharm」.ipynb「Jupyter Notebook」
(2023-11-19)Python3.11で動作確認済み
Trouble Support (getNumber) (setNext, support, resolve, done, fail) ↑ ↑ ↑ ↑ NoSupport LimitSupport OddSupport SpecialSupport (resolve) (resolve) (resolve) (resolve)class Trouble は,問題を提示します。
alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred)これでインスタンスに親子関係を記録できます。問題の提示と解決策巡りはメインルーチンでメソッド support を呼ぶだけです。メソッド support は次のようになっています。
22 23 24 25 26 27 28
def support(self, trouble): # トラブル解決の手順 if self.resolve(trouble): self.done(trouble) elif self.next: self.next.support(trouble) else: self.fail(trouble)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from abc import ABCMeta, abstractmethod class Trouble(object): def __init__(self, number): # トラブルの生成 self.number = number # トラブル番号 def getNumber(self): # トラブル番号を得る return self.number def __str__(self): # インスタンスがprintされると呼ばれる return "[Trouble {}]".format(self.number) class Support(metaclass=ABCMeta): def __init__(self, name): # トラブル解決者の生成 self.name = name # このトラブル解決者の名前 self.next = None # たらい回しの先 def setNext(self, next): # たらい回しの先を設定 self.next = next return next def support(self, trouble): # トラブル解決の手順 if self.resolve(trouble): self.done(trouble) elif self.next: self.next.support(trouble) else: self.fail(trouble) def __str__(self): # インスタンスがprintされると呼ばれる return "[{}]".format(self.name) @abstractmethod def resolve(self, trouble): # 解決用メソッド pass def done(self, trouble): print("{} is resolved by {}.".format(trouble, self)) def fail(self, trouble): # 未解決 print("{} cannot be resolved.".format(trouble)) class NoSupport(Support): # コンストラクタなし def resolve(self, trouble): # 解決用メソッド return False # 自分は何も処理しない class LimitSupport(Support): def __init__(self, name, limit): # コンストラクタ Support.__init__(self, name) self.limit = limit # この番号未満なら解決できる def resolve(self, trouble): # 解決用メソッド if trouble.getNumber() < self.limit: return True else: return False class OddSupport(Support): # コンストラクタなし def resolve(self, trouble): # 解決用メソッド if trouble.getNumber() % 2 == 1: return True else: return False class SpecialSupport(Support): def __init__(self, name, number): # コンストラクタ Support.__init__(self, name) self.number = number # この番号だけ解決できる def resolve(self, trouble): # 解決用メソッド if trouble.getNumber() == self.number: return True else: return False def main(): alice = NoSupport("Alice") bob = LimitSupport("Bob", 100) charlie = SpecialSupport("Charlie", 429) diana = LimitSupport("Diana", 200) elmo = OddSupport("Elmo") fred = LimitSupport("Fred", 300) # 連鎖の形成 alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred) # さまざまなトラブル発生 for i in range(0, 500, 33): alice.support(Trouble(i)) if __name__ == '__main__': main() """標準出力 [Trouble 0] is resolved by [Bob]. [Trouble 33] is resolved by [Bob]. [Trouble 66] is resolved by [Bob]. [Trouble 99] is resolved by [Bob]. [Trouble 132] is resolved by [Diana]. [Trouble 165] is resolved by [Diana]. [Trouble 198] is resolved by [Diana]. [Trouble 231] is resolved by [Elmo]. [Trouble 264] is resolved by [Fred]. [Trouble 297] is resolved by [Elmo]. [Trouble 330] cannot be resolved. [Trouble 363] is resolved by [Elmo]. [Trouble 396] cannot be resolved. [Trouble 429] is resolved by [Charlie]. [Trouble 462] cannot be resolved. [Trouble 495] is resolved by [Elmo]. """