はじめに:Strategyパターンはなぜ必要なのか?
Javaで開発をしていると、「処理は似ているけれど、中身だけ変えたい」という場面に必ず出会います。
例えば…
- 割引方法を切り替えたい
- 並び替えロジックを状況に応じて変えたい
- 支払い方法(クレジット・ポイント・現金)を切り替えたい
- ファイルの処理方法(コピー・削除・圧縮)を変えたい
こうしたケースで使われるのが Strategyパターン(ストラテジーパターン) です。
Strategyパターンとは、
「アルゴリズム(処理)を入れ替えられるようにするためのデザインパターン」
のこと。
しかし、従来の Strategy パターンは
「インターフェース + 複数の具象クラス」
という構造になりがちで、規模が大きくなるとクラス数が増えて大変…
そこで、Java8 以降で使える ラムダ式(匿名関数) を活用すると、
Strategyパターンの実装は劇的にスマートになります。
本記事では、プログラミング初心者や Java の学習者にも分かるように、
「ラムダ式 × Strategyパターン」 を実例満載で丁寧に解説していきます。
さらに、
- 具体的な実装例
- 応用パターン
- 現場での使われ方
- Java がこのパターンと相性抜群な理由
も合わせて解説します。
最後には学習ロードマップとして、
- 絶対にJavaプログラマーになりたい人へ。(https://amzn.asia/d/3E1CYbv)
- サイゼントアカデミー(https://academy.cyzennt.co.jp)
も紹介しています。
それではさっそく始めましょう。
【第1章】Strategyパターンとは?
Strategyパターンは、デザインパターンの中でも非常に有名で、初学者が必ず理解すべき重要パターンのひとつです。
Strategyパターンの目的はシンプルです。
▼ Strategyパターンの目的
- アルゴリズム(処理)を「ひとつのクラスに固定」しない
- アルゴリズムを自由に差し替えることができる
- 変更が必要な時、ほかのクラスに影響を与えない
よくある設計の失敗例として、「if 文で条件分岐を増やしすぎる」ケースがあります。
if (type.equals("add")) {
// 足し算処理
} else if (type.equals("sub")) {
// 引き算処理
} else if (type.equals("mul")) {
// 掛け算処理
}
このようなコードは、
- 分岐が増えると読みにくくなる
- 新しい処理を追加するとき if が増える
- テストしにくい
- 修正に弱い
というデメリットがあります。
そこで Strategy パターンを使うと、
「変更される可能性のある処理」を
ひとつの共通インターフェースでまとめる
という構造にできます。
【第2章】従来のStrategyパターン(クラスが多い…)
まずは従来の書き方を確認しておきましょう。
interface Strategy {
int execute(int a, int b);
}
class AddStrategy implements Strategy {
public int execute(int a, int b) {
return a + b;
}
}
class SubStrategy implements Strategy {
public int execute(int a, int b) {
return a - b;
}
}
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int execute(int a, int b) {
return strategy.execute(a, b);
}
}
使う側はこうなります。
Context context = new Context(new AddStrategy());
System.out.println(context.execute(10, 20));
▼ 従来方式の欠点
- クラスが増えすぎて管理が大変
- Strategy の数だけ新しいクラスを作る必要がある
- 初心者には理解しづらい
- コードが長くなる
【第3章】Java8以降:ラムダ式で Strategy が劇的にスマートに!
Java 8 以降では ラムダ式(匿名関数) が使えるようになりました。
ラムダ式は、
- 関数を「その場で定義して渡す」
- インターフェースを「実装するクラスを作らなくても良い」
という特徴があり、Strategy と非常に相性が良いです。
【第4章】ラムダ式での Strategy パターン(基本形)
まずは最小のコード。
@FunctionalInterface
interface Strategy {
int execute(int a, int b);
}
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int execute(int a, int b) {
return strategy.execute(a, b);
}
}
使う側:
Context add = new Context((a, b) -> a + b);
Context sub = new Context((a, b) -> a - b);
System.out.println(add.execute(10, 20)); // 30
System.out.println(sub.execute(10, 20)); // -10
▼ ラムダ式 Strategy のメリット
- クラスが不要
- その場で振る舞いを定義できる
- 可読性が高くなる
- 柔軟で拡張しやすい
Java の強みである「関数型インターフェース」と「ラムダ式」が組み合わさったことで、
Strategy パターンはより簡潔になりました。
【第5章】実務で使われる「Map × Strategy」
業務システムでは、特定のキーに応じて処理を切り替えることが多いです。
そのとき便利なのがこのスタイル。
import java.util.Map;
@FunctionalInterface
interface Strategy {
int exec(int a, int b);
}
class Calculator {
private static final Map<String, Strategy> strategies =
Map.of(
"add", (a, b) -> a + b,
"sub", (a, b) -> a - b,
"mul", (a, b) -> a * b
);
public static int calculate(String key, int a, int b) {
return strategies.get(key).exec(a, b);
}
}
使う側:
System.out.println(Calculator.calculate("mul", 3, 5)); // 15
▼ 特徴
- if / switch をゼロにできる
- 新しい戦略追加が超簡単
- Map の中身を見るだけで「どんな戦略があるか」分かる
実務で非常に好まれる書き方です。
【第6章】Strategyパターンの応用例
1:ファイル処理を Strategy 化
@FunctionalInterface
interface FileStrategy {
void handle(Path path) throws Exception;
}
FileStrategy copy = p -> Files.copy(p, Path.of("backup.txt"));
FileStrategy delete = p -> Files.delete(p);
copy.handle(Path.of("data.txt"));
2:バリデーションを Strategy 化
@FunctionalInterface
interface Validator {
boolean validate(String input);
}
Validator emailValidator = s -> s.contains("@");
Validator numberValidator = s -> s.matches("\\d+");
3:Spring Boot と Strategy
Spring ではよく「業務ロジックの切り替え」「優先度処理」で Strategy が使われます。
ラムダ式と組み合わせることで、さらにコードが見やすくなります。
【第7章】Java が Strategy パターンと相性抜群な理由
Java の強み
- マルチスレッドが強い
- JVM がエラーに強く堅牢
- 関数型インターフェースが強力
- ラムダ式で柔軟な実装ができる
特に Java 8 以降のアップデートで、
関数型の機能が大幅に強化されたため、
Strategy パターンのような「振る舞いを渡すパターン」と相性が良くなりました。
【第8章】最も美しい Strategy 実装(完成形)
@FunctionalInterface
interface Strategy {
int apply(int a, int b);
}
var strategies = Map.of(
"add", (Strategy)( (a, b) -> a + b ),
"sub", (Strategy)( (a, b) -> a - b ),
"mul", (Strategy)( (a, b) -> a * b )
);
System.out.println(strategies.get("mul").apply(3, 4));
これで 無駄なクラスはゼロ。
Strategy の「最も簡潔な形」と言えるでしょう。
【第9章】Java学習の次のステップ
Strategyパターンは Java において必ず通る道です。
しかし、Java を仕事にできるレベルに上げるには、
まだまだ多くの学習が必要です。
そんなあなたに2つの選択肢があります。
📘 自己学習で力をつけたい人へ
まずは文章で体系的に学ぶのがおすすめです。
👉 絶対にJavaプログラマーになりたい人へ。
https://amzn.asia/d/3E1CYbv
🎓 実務レベルのコードレビュー・転職サポートを受けたい人へ
自己学習で挫折しそう…
コードレビューをしてほしい…
転職もサポートしてほしい…
そんな人にはコレ。
👉 サイゼントアカデミー
https://academy.cyzennt.co.jp
Java に特化した学習環境で、
「初心者 → プログラマーへの転職」をサポートしています。
【まとめ】
本記事では、
- Strategyパターンの基本
- 従来の実装方法の課題
- ラムダ式によるスマート実装
- 実務で使える Map × Strategy
- 具体的な応用例
- Java が Strategy と相性が良い理由
- 学習の次のステップ
まで徹底的に解説してきました。
ラムダ式を使うことで、Strategyパターンはより強力で、
より読みやすく、より保守しやすくなります。
今後の Java 開発でも非常に役に立つ考え方です。
ぜひ、あなたのコードにも活かしてみてください!


コメント