SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

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

ラムダ式でStrategyパターンで実装されたコードをシンプルにする ~ そこから見えてくるストラテジオブジェクトの本質

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

考察:ラムダ式によって「計算を表すオブジェクト」という本質が見えてくる

 以上の例より、計算を表すオブジェクトは、ラムダ式によって簡潔に生成できることが分かります。

 前回紹介したCommandパターンの場合と同様に、ラムダ式を使うプログラム(リスト3)は、Strategyパターンのプログラム(リスト2)から、構造は大きく変わっていません。Logger クラスと TimestampFormatter インタフェースは、実質的に何も変更されていません。変わっているのは、時刻から文字列への変換を表す TimestampFormatter インタフェースのインスタンスを作るところだけです。リスト2では、クラスを宣言した上で、そのクラスをインスタンス化しているのに対して、リスト3では、ラムダ式で直接インスタンスを生成しています。基本的な構造が変わっていないため、ラムダ式バージョンのプログラムについても、Strategyパターンを採用しているとみなすことは可能です。

 しかしながら、前回Commandパターンの例として取り上げた亀シミュレータのラムダ式バージョンと、今回Strategyパターンの例として取り上げたログ出力プログラムのラムダ式バージョンを引き比べると、2つをわざわざ別のパターンとして分類することは不要と感じられるのではないでしょうか。

 亀シミュレータでは、亀を動かす処理をラムダ式で記述して渡しており、ログ出力プログラムでは、時刻から文字列への変換をラムダ式で記述して渡しています。どちらも、処理や計算をオブジェクトとして受け渡しているだけです。ラムダ式を用いて、クラスという夾雑物をプログラムから取り除くことによって、「処理や計算をオブジェクトとして扱う」という本質的な構造が直接的に現れるようになったために、あえてパターンとして分類する必要がなくなったわけです。

 Strategyの役割を果たすインタフェースは関数型インタフェースであることが多いため、ログ出力プログラムに限らず、ラムダ式に書き換えられる可能性があります。たとえば、2つのオブジェクトを比較する Comparator インタフェースは、compare メソッドを唯一の抽象メソッドとして持つ関数型インタフェースです。したがって、TreeSet クラスと Comparator インタフェースを使うリスト1のプログラムは、ラムダ式を使ってリスト5のように書き換えられます。

リスト5: LambdaEmployeeStorer.java
import java.util.*;

class Employee {
    private final String name;
    Employee(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
}

public class LambdaEmployeeStorer {
    public static void main(String[] args) {
        NavigableSet<Employee> employees = new TreeSet<>(
            (x, y) -> x.getName().compareTo(y.getName())
        );
        employees.add(new Employee("Stephen"));
        employees.add(new Employee("Aggi"));
        employees.add(new Employee("Katrina"));

        employees.forEach(e -> System.out.println(e.getName()));
        // 出力: Aggi <改行> Katrina <改行> Stephen
    }
}

 リスト5では、従業員オブジェクトを名前で比較するという計算を、ラムダ式を使って、その場で TreeSet クラスのコンストラクタに渡しています。ログ出力プログラムの場合と同様、プログラムの構造は大きく変わっていません。

 Strategyパターンのプログラムは、何がなんでもラムダ式を使って置き換えなければならない、というわけではもちろんありません。たとえば、計算が複雑であり、複数のメソッドに分割されているような場合は、ConcreteStrategyの役割を果たすクラスをそのまま保っておくほうがよいかもしれません。この他にも、CDIやSpring FrameworkのようなDIコンテナを使って、ストラテジオブジェクトを他のオブジェクトに注入する場合には、ConcreteStrategyをクラスとして宣言するほうが、容易に設定できることが多いでしょう。

おわりに

 次回は「Observerパターンをラムダ式で置き換える」方法について解説します。お楽しみに。

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
デザインパターンを置き換えよう! Javaラムダ式によるシンプルコーディング連載記事一覧

もっと読む

この記事の著者

宮川 拓(ミヤカワ タク)

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

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/8401 2015/01/20 14:00

イベント

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

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

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

メールバックナンバー