Java.use(better);

前の記事次の記事
Java.use(better);


Episode#08《改訂版》

Command パターンの応用 -- GoF を反面教師に


《関連記事》


《改訂版》

  • Scala に準拠するように、クラス/メソッドの名前を変更しました。
■ ハリウッドの原則

「ハリウッドの原則」に沿って、提供者(プログラマー)は、利用者(プログラマー)の便宜をはかるために、インターフェースと抽象クラス群を用意します。

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

》作業中です《

update*13/01/28 19:52:26