《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