@

from java.awt import Font
from javax.swing import JFrame
from javax.swing import JScrollPane
from javax.swing import JTextArea
from javax.swing import JTree
from TreeModel import Model

class Command(object):         # Command::Command
    def __init__(self, view):
        self.view = view

インスタンス属性 self.view を介して、ツリーの各ノード DefaultMutableTreeNode を参照できます。

    def __call__(self):
        raise NotImplementedError, self.__class__.__name__

特殊メソッド __call__ は、演算子 () に呼応して呼び出されます。実行時に例外 NotImplementedError を生成して、子孫クラスでこのメソッドを定義するように、プログラマーに注意を促します。

    def open(self, path, view):
        window = PopWindow(
            title = str(path),
            )
        window.contentPane.add(view)
        window.open()

class TreeCommand(Command):         # Command::ConcreteCommand
    def __call__(self):
        path = self.view.selectionPath.lastPathComponent
        model = Model(path)

        view = JTree(
            model.root.treeNode,
            valueChanged = self.view.valueChanged,
            )
        view = JScrollPane(view)
        self.open(path, view)

class TextCommand(Command):         # Command::ConcreteCommand
    def __call__(self):
        path = self.view.selectionPath.lastPathComponent

        view = JTextArea(
            font = Font("Courier", Font.PLAIN, 12),
            text = str(path.userObject),
            )
        view = JScrollPane(view)
        self.open(path, view)

子孫クラス TreeCommand/TextCommand では、抽象メソッド __call__ に対する具体的な動作を規定します。

■ モジュール:TreeView.py
...
from TreeCommand import TreeCommand, TextCommand

class View(JPanel):
    def init_buttons(self):
        panel = JPanel(GridLayout(1, 0))
        for label, command in [
            ("Tree", TreeCommand),
            ("Text", TextCommand),
        ]:
            button = CommandButton(
                label = label,
                command = command(self.tree),
                actionPerformed = self.actionPerformed,
                )
            panel.add(button)
        return panel

    def actionPerformed(self, e):
        e.source.command()    

前述した actionPerformed と違って、if 文が不要になるので、コードが汚染されるのを防ぎます。また、インスタンス属性 .command によって参照されるのは「呼び出し可能オブジェクト」なので、演算子 () に呼応して適切なメソッドを「動的に」起動します。

《Note》冗長なメソッド呼び出しが不要になるので、簡潔で見通しの良いコードを記述できるだけでなく、特定のプロトコルによってコードが汚染されるのを防ぎます。すると、開放閉鎖原則に沿って、このモジュールを閉じることができます。

class CommandButton(JButton): pass

クラス CommandButton は、便宜的に設けたもので、その本体は空 pass です。というのは、Java で記述されたリソースに対しては、インスタンス属性 .command を付加できないからです。