Java.use(better);
■ ハリウッドの原則
「ハリウッドの原則」に沿って、提供者(プログラマー)は、利用者(プログラマー)の便宜をはかるために、インターフェースと抽象クラス群を用意します。
public interface Reactor { public void execute(); }
インターフェース Reactor に準拠するクラス群を利用すると、特定のリスナーやイベントに依存しない抽象表現ができます。
abstract class ActionPerformed implements Reactor, ActionListener {
public void actionPerformed(ActionEvent e) { execute(); }
}
抽象クラス ActionPerformed は、インターフェース ActionListener に準拠するメソッド actionPerformed を隠蔽します。そこで、利用者は、リスナーやイベントの違いを意識せずに、メソッド execute の本体に、実行したい処理を記述します。
abstract class ButtonClicked extends ActionPerformed { protected AbstractButton source; public void listenTo(AbstractButton comp) { comp.addActionListener(this); source = comp; } }
抽象クラス ButtonClicked は、任意のコンポーネント AbstractButton にリスナーを登録するメソッド addActionListener を隠蔽します。そこで、利用者は、特定のコンポーネントに依存しないメソッド listenTo を利用して、リスナーをイベントが発生するコンポーネントと関係付けます。
□ イベントが発生したコンポーネントを特定する必要がない
単純な時計を事例に話を進めます。コンポーネントには、目に見えるもの(視覚部品)と見えないもの(機能部品)があります。後者の典型が javax.swing.Timer です。機能部品は操作できないので、イベントが発生したコンポーネントを特定する必要はありません。
new Timer(1000, new ActionPerformed() { public void execute() { update(); } }).start();
Timer のインスタンスを生成するときには、その引数にインターフェース ActionListener に準拠するものを指定します。これには ActionPerformed を利用できます。すると、利用者の操作ではなく、1000ms ごとに発生するイベントに呼応します。
public void update() { Date time = Calendar.getInstance().getTime(); setText(new SimpleDateFormat("HH:mm:ss").format(time)); }
メソッド update を呼び出すのは、Timer に限定されます。そこで、現在の時刻を獲得 getTime して、それを指定した書式 format で表示します。
前述した抽象クラス ActionPerformed/ButtonClicked を統合せずに、親子に分割した理由はこのためです。つまり、視覚部品には ButtonClicked を、機能部品には ActionPerformed を利用します。
↑ TOP
》作業中です《