今日のエントリーも「もっと Lambda」シリーズです。
今回はよく使われるデザインパターンで知られている Factory Method pattern を Java8 を使ってコーディングしてみます。
ちなみにこのネタは海外のサイトで紹介されていたものです。
それを少し変えて写経しただけですが随分シンプルになるので感激です。
それでは現在の Java だと下記のようになります。
package jp.yucchi.factorymethodpattern4oldjava;
public interface Airplane {
public void pilot();
public void maintain();
}
package jp.yucchi.factorymethodpattern4oldjava;
public class JetAirplane implements Airplane {
@Override
public void pilot() {
System.out.println("ジェット機を操縦します。");
}
@Override
public void maintain() {
System.out.println("ジェット機を整備します。");
}
}
package jp.yucchi.factorymethodpattern4oldjava;
public class FighterPlane implements Airplane {
@Override
public void pilot() {
System.out.println("戦闘機を操縦します。");
}
@Override
public void maintain() {
System.out.println("戦闘機を整備します。");
}
}
package jp.yucchi.factorymethodpattern4oldjava;
abstract class AirplanePilot {
public abstract Airplane getAirplane();
public void pilotAirplane() {
getAirplane().pilot();
}
public void maintainAirplane() {
getAirplane().maintain();
}
}
class JetAirplanePilot extends AirplanePilot {
@Override
public Airplane getAirplane() {
return new JetAirplane();
}
}
class FighterPlanePilot extends AirplanePilot {
@Override
public Airplane getAirplane() {
return new FighterPlane();
}
}
package jp.yucchi.factorymethodpattern4oldjava;
public class FactoryMethodPattern4OldJava {
public static void main(String[] args) {
pilotAirplane(new JetAirplanePilot());
pilotAirplane(new FighterPlanePilot());
}
private static void pilotAirplane(AirplanePilot aPilot) {
System.out.println("I pilot a new airplane.");
aPilot.pilotAirplane();
aPilot.maintainAirplane();
}
}
Factory Method pattern でよく見かける典型的なサンプルですね。
インスタンスの生成をサブクラスに任せることによって柔軟に生成するインスタンスを選択することを可能としています。
では Java8 ではどのようなコードになるのでしょうか?
package jp.yucchi.factorymethodpattern4lambda;
public interface Airplane {
public void pilot();
public void maintain();
}
package jp.yucchi.factorymethodpattern4lambda;
public class JetAirplane implements Airplane {
@Override
public void pilot() {
System.out.println("ジェット機を操縦します。");
}
@Override
public void maintain() {
System.out.println("ジェット機を整備します。");
}
}
package jp.yucchi.factorymethodpattern4lambda;
public class FighterPlane implements Airplane {
@Override
public void pilot() {
System.out.println("戦闘機を操縦します。");
}
@Override
public void maintain() {
System.out.println("戦闘機を整備します。");
}
}
package jp.yucchi.factorymethodpattern4lambda;
public interface AirplanePilot {
public Airplane getAirplane();
public default void pilotAirplane() {
getAirplane().pilot();
}
public default void maintainAirplane() {
getAirplane().maintain();
}
}
package jp.yucchi.factorymethodpattern4lambda;
public class FactoryMethodPattern4Lambda {
public static void main(String[] args) {
pilotAirplane(JetAirplane::new);
pilotAirplane(FighterPlane::new);
}
static void pilotAirplane(AirplanePilot aPilot) {
System.out.println("I pilot a new airplane.");
aPilot.pilotAirplane();
aPilot.maintainAirplane();
}
}
Java8 では抽象化クラス AirplanePilot とそれの具象化クラス二つが必要とされません。
その代わりに、Java8 の新機能の Default methods ( Virtual extension methods ) を実装したインターフェイスを利用します。
実行結果はどちらも次のようになります。
I pilot a new airplane.
ジェット機を操縦します。
ジェット機を整備します。
I pilot a new airplane.
戦闘機を操縦します。
戦闘機を整備します
実にシンプルで綺麗なコードで Factory Method pattern が実装できてしまうんですね!