今回は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 件のコメント:
コメントを投稿