SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

デザインパターンを置き換えよう! Javaラムダ式によるシンプルコーディング

ラムダ式でObserverパターンで実装されたコードをシンプルにする ~ オブザーバオブジェクトはラムダ式によって簡潔に生成できる

デザインパターンを置き換えよう! Javaラムダ式によるシンプルコーディング 第3回


  • このエントリーをはてなブックマークに追加

 Java SE 8で追加された構文要素「ラムダ式」を使うと、デザインパターンで解決しようとしていた問題を、ずっと素直なコードで実装できます。本連載では、デザインパターンを使って書かれたコードを、ラムダ式を使ってシンプルなコードに書き換えながら、ラムダ式の使いどころ・使い方を学んでいきます。今回行うのは、Observerパターンの書き換えです。

  • このエントリーをはてなブックマークに追加

Observerパターンのおさらい

 Observerパターンは、何かの状態変更への対応をオブジェクトとして表すものです。Observerパターンを使うことで、状態変更の発生と対応を別個に実装できます。典型的なObserverパターンのプログラムには、図1に示すようなクラスおよびインタフェースが登場します。

図1:Observerパターンのクラス図
図1:Observerパターンのクラス図

 

 それぞれのクラス、インタフェースの役割は次のとおりです。

  • Subject:状態変更の発生源の抽象クラス
  • ConcreteSubject:具体的な状態変更の発生源のクラス
  • Observer:状態変更への対応を表すオブザーバオブジェクトのインタフェース
  • ConcreteObserver:状態変更への具体的な対応を表すオブザーバオブジェクトのクラス
  • クライアント:ConcreteSubjectにオブザーバを登録するクラス1

[1] クライアントの役割は、GoF[1994](書籍『オブジェクト指向における再利用のためのデザインパターン』)には列挙されていませんが、本稿では説明を簡潔にするためにこれを採用します。

 典型的なObserverパターンのプログラムは、図2に示すようなシーケンスで動作します。

図2:Observerパターンのシーケンス図
図2:Observerパターンのシーケンス図

 

 すなわち、Observerパターンのプログラムはおおまかに次の2ステップで動作します。

  1. オブザーバオブジェクトをConcreteSubjectに登録する
  2. ConcreteSubjectの状態が変更された際に、オブザーバオブジェクトに通知する

 SwingやJavaFXといったGUIツールキットの多くはObserverパターンを採用しています。例えば、ウィンドウのリサイズやドラッグ&ドロップの開始/終了のような状態変更に対処するイベントハンドラは、オブザーバオブジェクトだと考えられます。

 例として、リサイズに追随してウィンドウのサイズを表示するJavaFXプログラムはリスト1のように書けます。

リスト1:WindowSizeMonitor.java
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;

public class WindowSizeMonitor extends Application {

    /** 表示領域. */
    private final BorderPane pane = new BorderPane();

    /** ウィンドウのシーン. */
    private final Scene scene = new Scene(this.pane, 600, 400);

    /**
     * 表示領域にウィンドウサイズを表示する.
     */
    private void showSize() {
        String message = String.format("%s x %s", scene.getWidth(), scene.getHeight());
        pane.setCenter(new Label(message));
    }

    /**
     * リサイズのイベントハンドラ.
     */
    class ResizeListener implements ChangeListener<Number> {
        @Override
        public void changed(ObservableValue<? extends Number> prop, Number oldNum, Number newNum) {
            showSize();
        }
    }

    @Override
    public void start(Stage stage) {
        showSize();

        // イベントハンドラをシーンに登録
        scene.widthProperty().addListener(new ResizeListener());
        scene.heightProperty().addListener(new ResizeListener());

        stage.setScene(scene);
        stage.setTitle("Window Size Monitor");
        stage.show();
    }

    public static void main(String[] args) {
        launch(WindowSizeMonitor.class, args);
    }
}
図3:リスト1のJavaFXプログラムの実行結果
図3:リスト1のJavaFXプログラムの実行結果

 

 リスト1の中で、Observerパターンに登場する役割は、それぞれ次のようなクラス・インタフェースによって担われています。

  • Subject, ConcreteSubject:Scene クラス
  • Observer:ChangeListener インタフェース
  • ConcreteObserver:ResizeListener クラス

 GUIツールキットにおいて、本連載の第1回で紹介したCommandパターンとObserverパターンの区別は微妙です。例えば、フォトレタッチソフトで、「ボタンが押下された」という状態変更に対応して画像にエフェクトを掛ける処理を行うような場合は、Observerパターンというよりも、一群の処理をオブジェクトとして表すCommandパターンとみなすほうが自然かもしれません。

 Observerパターンは、オブジェクト指向プログラミングの世界の外にも見出すことができます。例えば、出版-購読モデル(Pub/Sub) というメッセージング方式が挙げられます。

 出版-購読モデルでは、メッセージの送信者を「出版者」と呼び、これはObserverパターンにおけるSubjectに相当します。またメッセージ受信者を「購読者」と呼び、これはObserverに相当します。出版者は具体的な購読者のことを知らずにメッセージを送信でき、購読者も具体的な出版者を知らずにメッセージの受信を申し込んだり、取り消したりできます。したがって、出版-購読モデルもObserverパターンと同様に、メッセージの送信者と受信者の独立性を保ちつつやりとりを可能にするためのパターンだといえます。

 出版-購読モデルは、例えばJava標準のメッセージングAPIであるJMS(Java Message Service)や、Amazon Web ServicesのメッセージングサービスであるSimple Notification Service(SNS)などがサポートしています。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
ジョブコントローラ(Observerパターン)

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
デザインパターンを置き換えよう! Javaラムダ式によるシンプルコーディング連載記事一覧

もっと読む

この記事の著者

宮川 拓(ミヤカワ タク)

日本Javaユーザーグループ幹事。東京のシステムインテグレータに勤務。Java VM上で動作する言語である「Kink」を開発中。相撲とアメリカ文学とスコティッシュポップを愛する。 ・ブログ: http://d.hatena.ne.jp/miyakawa_taku/ ・Twitter: @miyakawa_taku

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8504 2015/03/12 21:10

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング