Python 弾丸ツアー #DP: ツリー ... step 4: 《Point》ゴミの分別は誰が

OOPデザインパターンリファクタリング

Python.use(better); Python 弾丸ツアー #DP: Tkinter/Python
>>> ツリー(階層構造)
step 4: 《Point》ゴミの分別は誰が
《Python3.1|Jython2.5|IronPython2.6》

《著》小粒ちゃん@湘南組《監修》小泉ひよ子とタマゴ倶楽部
第0版♪2001/03/02 ● 第1版♪2003/05/23 ● 第4版♪2010/03/08

step 4: コードの解説

《Point》ゴミの分別は誰が:ゴミの分別は「それ自身 self に任せる」のが、OOP の戦略的な特徴のひとつです。step3 では、

    def makeTree(self):
        ...
        tab_folder = "  - "
        tab_file   = "  . "

        T = self.tree
        for indent, dir, node in zip(           # ファイル or フォルダー
            T.indents(), T.dirs(), T.nodes()
        ):
            self.createNode(
                ...
                tab=tab*indent+(tab_file, tab_folder)[dir],
                image=(self.fileImage, self.dirImage)[dir],
                ...

for 文に続く制御変数 dir によって、ファイルかフォルダーかを分別する(if 文と同等の効果)必要があります。step4 では「分割統治の原則」に沿ってリファクタリングを実施したので、

    def visitLeaf_(self, node, indent):         # ファイル
        ...
        tab2 = "  . "
        self.client.append(
            ...
            tab=tab1*indent+tab2,
            image=self.client.fileImage,
            ...

    def visitComposite_(self, node, indent):    # フォルダー
        ...
        tab2 = "  - "
        self.client.append(
            ...
            tab=tab1*indent+tab2,
            image=self.client.dirImage,
            ...
        for e in node:
            e.accept_(TreeVisitor(self.client), indent+1)

ファイルとフォルダーとは分別して処理されます。すると、if/for が不要になるだけでなく「相互の存在に依存しない」洗練されたコードを記述できます。つまり、利用者がゴミを分別しなくても、ゴミは自分で判断して適切な場所に収納されるのです。□

■ TreeWidget
## ----------------------------------------
class TreeWidget(object):
    def __init__(self, tree=None, path=None, **keys):
        self.items = []
        self.top    = self.create_Toplevel(tree=tree)
        self.widget = self.create_widget(master=self.top, tree=tree)

    def create_Toplevel(self, tree):
        widget = Toplevel()

        s = tree.path.split("/")
        title = "%s: %s"%(s[-1],"/".join(s[:-1]))

        widget.title(title)
        widget.config(padx=16, pady=4)
        return widget

 ̄クラス TreeWidget では、共通するプロトコルを規定します。

    def __init__(self, tree=None, path=None, **keys):
        self.items = []
        self.top    = self.create_Toplevel(tree=tree)
        self.widget = self.create_widget(master=self.top, tree=tree)

 ̄メソッド __init__ では、各インスタンス属性を初期設定します。

  • インスタンス属性 self.widget は、ツリーを表示する部品を管理します。これは、子孫クラスで実現するメソッド create_widget に依存します。
    def create_Toplevel(self, tree):
        widget = Toplevel()
        ...
        return widget

 ̄メソッド create_Toplevel では、新たな Toplevel を生成して、その widget をリターン値にします。

TOP
》作業中です《