導入
第4章のStrategyパターンでは、NoDiscount・PercentDiscount・FixedDiscount と、割引方法1つにつきクラスを1つ作りました。ちゃんとした設計ですが、「たった1行の計算式」のためにクラスファイルを1つ用意するのは大げさに感じることもあります。Javaの 関数インタフェース と ラムダ式 を使うと、Strategyの考え方そのままに、実装をぐっと短く書けます。
説明
メソッドが1つしかないインタフェース(関数インタフェース)は、クラスを定義せずに ラムダ式 でその場に実装を書けます。
interface DiscountStrategy {
int apply(int price);
}
public class Main {
public static void main(String[] args) {
// クラスを作らず、ラムダ式でその場に実装を渡す
Cart cart = new Cart(price -> price - price * 10 / 100);
System.out.println(cart.checkout(1000)); // 900
// 固定額オフも、その場で書ける
cart.setStrategy(price -> price - 200);
System.out.println(cart.checkout(1000)); // 800
}
}
graph LR A["従来: PercentDiscount クラスを定義"] --> B["Cart に new PercentDiscount(10) を渡す"] C["ラムダ: price -> price - price * 10 / 100"] --> D["Cart にその場で渡す(クラス定義不要)"]
price -> price - price * 10 / 100…DiscountStrategyの唯一のメソッドapply(int price)の中身だけをその場に書いたものです。priceが引数、->の右側が「返す式」です。new Cart(price -> ...)は、実質的にnew Cart(new PercentDiscount(10))(第4章のコード)と同じ動作をします。違いは、PercentDiscountというクラスをわざわざファイルとして定義する必要がないことだけです。java.util.functionパッケージにはFunction<T, R>(1引数を受け取り1つ返す)などの汎用的な関数インタフェースが用意されており、自分でDiscountStrategyを定義しなくても済むケースも多くあります。- 注意点もあります。ラムダは「その場限りの小さな処理」に向いていますが、状態を持ったり、複数のメソッドが必要だったり、名前をつけて意味を明確にしたい場合は、これまで通りクラス(
PercentDiscountのような)で実装したほうが読みやすいこともあります。「短く書けるから常にラムダ」ではなく、状況に応じた使い分けが大切です。