考察:ラムダ式がCommandパターンをそれと意識して用いる必要をなくした
以上の例のようにラムダ式を使うことによって、動作を表すオブジェクトの生成はより簡潔になります。
Java SE 8バージョンのプログラムは、元の(Java SE 7版の)プログラムから大きく構造が変化しているわけではありません。TurtleMover クラスの内容は一言一句変更されていませんし、亀の動作を Motion インタフェースで表すことにも変わりはありません。このため、Java SE 8バージョンのプログラムは、動作を表すコマンドオブジェクトをラムダ式によって生成しているのであり、依然としてCommandパターンを採用しているとみなすことも可能ではあります。
しかしながら、前述したとおり、そもそもラムダ式は具体的な「処理」や「動作」をオブジェクトとして生成する言語機能です。したがって、あえてCommandパターンという用語を使うまでもなく、単に「文字に対応する動作をラムダ式で与えている」と捉えるほうが自然でしょう。ラムダ式の導入によってJava言語の表現力が増したことにより、わざわざCommandパターンをそれと意識して用いる必要がなくなったのです。
既存のプログラムの構造をそのままにラムダ式が使えるという特徴は、当然ながら今回の亀シミュレータだけに限った話ではありません。例を挙げると、前述したExecutorフレームワークで用いられる Runnable インタフェース、Callable インタフェースなど、Commandの役割を担うような、動作を表すインタフェースは、その多くが関数的インタフェースでもあります。したがって、既存のプログラムで、これらインタフェースを実装するクラスのインスタンスを生成している箇所は、軒並みラムダ式で書き換えられるというわけです。例えば、doSomething メソッドを呼び出すタスクを、Executorフレームワークのスレッドプールエクゼキュータにサブミットする処理は、ラムダ式を使ってリスト8のように書けます。
スレッドプールエクゼキュータにサブミットする処理
threadPool.submit(() -> doSomething());
ただし、Commandパターンを採用したすべてのプログラムが、いつもラムダ式を使って置き換えるのに適しているわけではありません。
例えば、コマンドオブジェクトによって表される動作が複雑であり、ConcreteCommandの役割を担うクラスが複数のメソッドに分割されているような場合には、あえてラムダ式に置き換える必要はないかもしれません。一連の複雑な動作がひとつのクラスとしてまとまっていることにより、プログラムの見通しがよくなるためです。
その他にも、アンドゥ、リドゥのような高度な機能を実現するため、Commandの役割を担うインタフェースに複数の抽象メソッドが定義されていることがあります。このようなインタフェースは関数的インタフェースではないため、コマンドオブジェクトの生成を直接的にラムダ式で置き換えることはできません。
おわりに
次回は「Strategyパターンをラムダ式で置き換える」方法について解説します。お楽しみに。
