例題で学ぶデザインパターン #15:JButton を利用する:仕様変更
例題で学ぶ Jython/Swing デザインパターン《Jython2.5》
JButton を利用する:仕様変更
■ 概要
例題により、アプリケーションを作成する過程を通して、Jython/Swing によるデザインパターンを習得します。
この課題では、Swing/GUI を使って階層構造を持つ情報を提示します。〈GoF〉Composite/Iterator/Visitor/Command パターンを導入すると、if/for 文によるコードの汚染、配列の境界問題が解消されるので、要求仕様の変更にも柔軟に対処でき、簡潔で見通しの良いコードを記述できるようになります。
《Note》JPython1.1.x/Jython2.1.x 用に作成したセミナー課題を、Jython2.5 で再構成しました。
事例:モジュールを起動する
モジュールを起動すると、次のようなウィンドウが現れます。
$ jython2.5b3 -i step13/TreeEx.py JTree を頂点とするツリー/sports を頂点とする部分ツリー/football ノード
ボタン〔Text〕を押すと、選択したノードを頂点とする部分ツリーが、新たなウィンドウ JTextArea に表示されます。
事例:コードの解説
■ モジュール:TreeView.py
class View(JPanel): def init_buttons(self): panel = JPanel(GridLayout(1, 0)) for label in "Tree", "Text": button = JButton( label = label, actionCommand = label, actionPerformed = self.actionPerformed, ) panel.add(button) return panel def actionPerformed(self, e): command = e.source.actionCommand if command == "Tree": # (x_x) oops ... self.tree_actionPerformed(e) if command == "Text": # (x_x) oops ... self.text_actionPerformed(e)
actionCommand によって、各ボタンを識別します。
《Note》何が問題か:仕様変更などにより、新たな機能が必要になるたびに、if 文が追加されます。すると、このモジュールを永遠に閉じられずに「開放閉鎖原則」に背く if 文によって、コードは汚染 されます。そこで、この問題を解消するために〈GoF〉Command パターンを導入した事例を 次項 で紹介します。
def tree_actionPerformed(self, e): path = self.tree.selectionPath.lastPathComponent model = Model(path) view = JTree( model.root.treeNode, valueChanged = self.valueChanged, ) view = JScrollPane(view) window = PopWindow( title = str(path), ) window.contentPane.add(view) window.open() def text_actionPerformed(self, e): path = self.tree.selectionPath.lastPathComponent view = JTextArea( font = Font("Courier", Font.PLAIN, 12), text = str(path.userObject), ) view = JScrollPane(view) window = PopWindow( title = str(path), ) window.contentPane.add(view) window.open()
メソッド tree_actionPerformed/text_actionPerformed では、ボタンを選択したとき具体的な動作を規定します。
《Note》何が問題か:これらのメソッド呼び出しを事前に規定しておく必要があるので、柔軟性に欠けます。すべての要求仕様が確定するまで、このモジュールは開いたままで、閉じることができません。
Tips
》作業中です《