《Jython2.5》JTree〈GoF〉Visitor を実現する
Java プログラマーのための Python 導入ガイド〈初級/応用編〉《Jython2.5》
JTree〈GoF〉Visitor を実現する
■ 概要
フォルダー/ファイルの階層構造を Swing/GUI を利用して「簡単に」閲覧できるツールがあると便利です。
この課題では、Swing/GUI を使って階層構造を持つ情報を提示します。 また〈GoF〉Composite/Iterator/Visitor/Command パターンを導入することで、 構造化プログラミングには必須の if/for が不要になるので、簡潔で見通しが良く、 要求仕様の変更にも柔軟に対処できる、プログラム(コード)を作成する方法を紹介します。 《Note》JPython1.1.x/Jython2.1.x 用に作成したセミナー課題を、Jython2.5 で再構成しました。
■ 関連記事
- Java/Python 導入ガイド:Swing/Jython2.5 - JTree - 続・ひよ子のきもち
- Python.use(better, anti=”GoF”) Let's GoFoward, GoF を反面教師に
事例:コードの解説
■ GoF を反面教師に…
class Node(object): # Composite::Component
def accept(self, visitor, arg=0):
eval("visitor.visit%s(self, arg)"%self.__class__.__name__)
GoF の記述を鵜呑みにすると、損をします。Smalltalk と同様に、メタプログラミングを活用して、クラス名をもとに「動的に」メソッド呼び出しを行う仕組みを導入するなら、子孫クラスで個別の accept を定義する必要はありません。
今回の例題では、高々2つのクラスしか登場しませんが、実際のアプリケーション開発では、多数のクラスを対象するのが常です。なにより、要求仕様の変更の度に、新たな accept を定義する必要がなくなるので、より本質的な問題解決に専念できるようになります。
⇒ 続きはこちら 》GoF を反面教師に《 で
■ テキストによる表示:シーケンス処理を基調に
選択したノードの傘下を、テキスト(JTextArea)で表現します。
class TextVisitor(Visitor):
def __init__(self):
self.tree = []
def __str__(self):
return "\n".join(self.tree)
インスタンス属性 self.tree には、Visitor によって得られた情報を累積します。
def visitFileNode(self, node, indent):
self.tree += ["%s%s%r (%d)"%(
self.tab1*(indent-1), self.tab2, node, node.getsize())]
各ファイル node では、インデント(深さ)indent に相当するタブに続いて、node の名前とサイズ getsize() を表示します。
def visitDirNode(self, node, indent):
self.tree += ["%s%s%r"%(
self.tab1*(indent-1), self.tab2*(not not indent), node)]
各フォルダー node では、ツリーの枝(branch)に位置するので、インデント(深さ)indent に相当するタブに続いて、node の名前を表示します。
■ ツリーによる表示:再帰的な構造に沿って
選択したノードの傘下を、ツリー(JTree)で表現します。
class TreeVisitor(Visitor): def visitFileNode(self, node, parent): pass
ファイル node は、ツリーの末端(leaf)に位置するので、何もしません。つまり、このメソッドが、再帰呼び出しの「停止条件」に相当します。
def visitDirNode(self, node, parent): for e in node.treeNode.children(): current = e.userObject child = DefaultMutableTreeNode(current) parent.add(child) current.accept(TreeVisitor(), child)
フォルダー node は、ツリーの枝(branch)に位置するので、その子 treeNode.children() をたどる必要があります。その子 current に対して、さらに accept を適用することで、再帰的な構造にもうまく対処できます。
current は、ファイル/フォルダーのどちらかの可能性がありますが、それは実行時に確定するので、その処理を TreeVisitor に委ねます。すると(構造化プログラミングを象徴する)if による条件分岐が不要になるので、簡潔で見通しの良いコードを記述できるようになります。
Tips
》作業中です《