今回はChain of Responsibility。UIなどでよく使われるパターンだそうです。
というのも、UIはビューコンポーネントのようなものを入れ子にして構成されることが多く、
(Window → Canvas → TextField 的な)
そのUIをユーザがクリック(タップ)したりキーボード操作したりする『要求』に対し、その要求をどのコンポーネントが処理するかは、普通『たらい回し』にされることが多いからです。
(上の例だと TextField → Canvas → Window)
すなわち、Chain of Responsibilityパターンは
- (主にユーザなどによる)要求があり
- その要求の処理先を動的に設定したい
時に最適なパターンと言えそうです。
また、Compositeパターンなどの再帰的構造でよく使うそうです。
実行結果
[0] is resolved by [Bob]. [33] is resolved by [Bob]. [66] is resolved by [Bob]. [99] is resolved by [Bob]. [132] is resolved by [Danie]. [165] is resolved by [Danie]. [198] is resolved by [Danie]. [231] is resolved by [Elmo]. [264] is resolved by [Fred]. [297] is resolved by [Elmo]. [330] cannot be resolved. [363] is resolved by [Elmo]. [396] cannot be resolved. [429] is resolved by [Charlie]. [462] cannot be resolved. [495] is resolved by [Elmo].
ソースコード
#!/usr/bin/env python # -*- coding: utf8 -*- class Trouble: def __init__(self, number): self.number = number def __str__(self): return "[%d]" % (self.number) class Support: def __init__(self): raise Exception("Abstract class") def __str__(self): return "[%s]" % self.name # final method - template method def support(self, trouble): if self._resolve(trouble): self._done(trouble) elif self.next is not None: self.next.support(trouble) else: self._fail(trouble) def _resolve(self, trouble): raise NotImplementedError def _done(self, trouble): print "%s is resolved by %s." % (trouble, self) def _fail(self, trouble): print "%s cannot be resolved." % (trouble) def setNext(self, next): self.next = next return self.next class NoSupport(Support): def __init__(self, name): self.name = name self.next = None def _resolve(self, trouble): return False class LimitSupport(Support): def __init__(self, name, limit): self.name = name self.limit = limit self.next = None def _resolve(self, trouble): return True if trouble.number < self.limit else False class OddSupport(Support): def __init__(self, name): self.name = name self.next = None def _resolve(self, trouble): return True if trouble.number % 2 == 1 else False class SpecialSupport(Support): def __init__(self, name, number): self.name = name self.number = number self.next = None def _resolve(self, trouble): return True if trouble.number == self.number else False def main(): m_alice = NoSupport("Alice") m_bob = LimitSupport("Bob", 100) m_charlie = SpecialSupport("Charlie", 429) m_danie = LimitSupport("Danie", 200) m_elmo = OddSupport("Elmo") m_fred = LimitSupport("Fred", 300) m_alice.setNext(m_bob).setNext(m_charlie).setNext(m_danie).setNext(m_elmo).setNext(m_fred) for i in xrange(0, 500, 33): m_alice.support(Trouble(i)) if __name__=='__main__': main()
0 件のコメント:
コメントを投稿