例題で学ぶデザインパターン #1.3: モジュール分割

前の記事記事一覧次の記事

例題で学ぶ Jython/Swing デザインパターン《Jython2.5》
モジュール分割

《著》越智ことり+小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第1版♪2003/05/23 ● 第2版♪2009/04/03

■ 概要

アプリケーションを作成する過程を通して、Jython/Swing によるデザインパターンを習得します。

この課題では、Swing/GUI を使ってモデルの変化に呼応する複数のビューを提示します。〈GoF〉Observer パターンを導入すると、依存性を扱うのが容易になるので、要求仕様の変更にも柔軟に対処でき、簡潔で見通しの良いコードを記述できるようになります。

《Note》JPython1.1.x/Jython2.1.x 用に作成したセミナー課題を、Jython2.5 で再構成しました。

事例:モジュールを起動する

モジュールを起動すると、次のようなウィンドウが現れます。

$ jython2.5.0 -i step03/ListEx.py 


(左)リスト JList を構成する各項目を選択すると、(右)キャンバス Canvas の背景色が変化します。たとえば、ノード aquamarine を選択すると、キャンバスの背景がその色に変化します。

$ ls -l step03
total 48
-rw-r--r--@ 1 sketch  staff  2280  6 22 23:34 ListEx.py
-rw-r--r--  1 sketch  staff  4500  6 22 23:35 ListModel$py.class
-rw-r--r--@ 1 sketch  staff   410  6 22 23:35 ListModel.py
-rw-r--r--  1 sketch  staff  3583  6 22 23:35 ListView$py.class 
-rw-r--r--@ 1 sketch  staff   357  6 22 23:35 ListView.py

モジュールを起動すると、同時に、クラスファイル .class が生成されます。

事例:モジュールを分割する

リファクタリングの第一歩は、モジュールを分割することです。リファクタリングの前後で、機能は変化しませんが、その後の作業を楽にします。


ここでは、既存のモジュール ListEx.py を、複数のモジュール ListModel.py/ListView.py に分割します。

事例:コードの解説

■ モジュール TreeEx.py
from java.awt import BorderLayout
from javax.swing import JFrame
from javax.swing import JList
from javax.swing import JPanel
from javax.swing import JScrollPane
from pawt import colors
from sys import argv

from java.awt import Canvas
from javax.swing import JSplitPane

モジュール分割によって、不要になった from..import 文を削除します。

from ListModel import Model
from ListView import ListView, CanvasView

モジュール分割によって、必要になった from..import 文を追加します。

class View(JPanel):
    def __init__(self, *args, **keys):
        self.model = Model()

        list = ListView(
            self.model.listData,
            valueChanged = self.valueChanged,
            )
        self.canvas = CanvasView()

既存のクラス JList/Canvas に代えて、新たなモジュールで定義したクラス ListView/CanvasView を利用します。

    def valueChanged(self, e):
        value = e.source.selectedValue
        self.canvas.background = self.model.color(value)

インスタンス属性 self.model を介して、メソッド color を利用すると、表示したい色情報が得られます。

《Note》モジュールの連続性:色情報を獲得する具体的な方法(how)に依存しない、その目的(what)だけを銘記した抽象表現が可能になります。たとえば、要求仕様の変更により、色情報を獲得する方法が変更されても、その影響はメソッドを「提供する」側のモジュール内に限定され、メソッドを「利用する」側のモジュールは影響を受けません。

■ モジュール TreeModel.py
from pawt import colors

class Model(object):
    listData = [e for e in dir(colors) if not e.startswith("_")]

    def color(self, value):
        return eval("colors.%s"%value)

他のモジュールで削除した from..import 文を、このモジュールに移動します。

■ モジュール ListView.py
from java.awt import Canvas
from javax.swing import JList

class ListView(JList):
    pass
class CanvasView(Canvas):
    pass

他のモジュールで削除した from..import 文を、このモジュールに移動します。リファクタリングを実施しただけなので、クラスの本体は空 pass になっています。

Tips

》作業中です《

Last updated♪09/06/23