《38》デザインパターン〈GoF〉Template〈Python 2.x 版〉
実録:はじめてのプログラミング《記事一覧》
《38》デザインパターン〈GoF〉Template
《著》小粒ちゃん+α《監修》小泉ひよ子とタマゴ倶楽部
2009年3月6日(金)
今日の進捗
- Language Reference: Numeric and Mathematical Modules; functools — Higher order functions and operations on callable objects
- Python.use(better) -- セミナー研修テキスト
- 連結リスト課題を「続・ひよ子のきもち」で公開
Comment | |
---|---|
本人:野中 | テンプレートは穴埋め問題の意味をやっと実感できるようになりました。 |
担当:伊藤/本間 | 。(^^) |
デザインパターン〈GoF〉Template
カタログには〈GoF〉Template として紹介されている、デザインパターンは、ここでもその効能を発揮します。(前述した)3つののメソッドはすべて、次のように、
def __delitem__(self, key): self.removeNode(key, "delitem") def remove(self, value): self.removeNode(value, "remove") def pop(self): return self.removeNode(None, "pop")
メソッド removeNode を再利用しているので、その違いを実引数("delitem"/"remove"/"pop")で指定できます。これらのメソッドの違いは、テンプレートを通して見ると、次のように、
def __delitem__(____, key): ____.__________(key, "delitem") def remove(____, value): ____.__________(value, "remove") def pop(____): return ____.__________(None, "pop")
その違いだけが浮き彫りになります。また、先述した、
def _removeNode_delitem(self, prev, node): return self._removeNode_body(prev, node) def _removeNode_remove(self, prev, node): return self._removeNode_body(prev, node) def _removeNode_pop(self, prev, node): self.tail = prev return self._removeNode_body(prev, node, node.item)
についても同様に、テンプレートを通して見ると、次のように、
def _removeNode_delitem(____, ____, node): return ____.________________(____, ____) def _removeNode_remove(____, ____, node): return ____.________________(____, ____) def _removeNode_pop(____, ____, node): self.tail = prev return ____.________________(____, ____, node.item)
その違いだけが浮き彫りになります。さらに、これらの違いを具体的に知りたいときには、たとえば、
def _removeNode_delitem_cond(self, node, key, n): return n==key # 添字が一致する def _removeNode_remove_cond(self, node, value, n): return node.item==value # 値 が一致する def _removeNode_pop_cond(self, node, value, n): return node==self.tail # 末尾と一致する
という具合に、各機能に固有の問題解決に専念できる〔関心の分離〕という効果が期待できます。最後に、リファクタリングの成果を示すと、次のようになります。
class myList(object): def removeNode(self, value, tag): prev, node = self.head, self.head.next n = 0 while node: if eval("self._removeNode_%s_cond@(node,value,n)"%tag): return eval("self._removeNode_%s@(prev,node)"%tag) prev, node = node, node.next n += 1 else: s = self.__class__.__name__ eval("self._removeNode_%s_error@(s)"%tag) def _removeNode_body(self, prev, node, value=None): prev.next = node.next del node return value
Tips
このアプローチの意義は、それを実現する手段に依存しない抽象的な記述が可能になることです。すると、同じ機能を他のデータ構造などを利用して実現するときに、その変更の影響を受けないので、アジャイル開発を促進します。《うさぎ》□
Last updated♪09/03/05