@
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 を付加できないからです。