では「練習問題4:ログレベル出力」を 戦略パターンでリファクタリングした解答例を示します。
元のコード(フォールスルーあり)
switch (logLevel) {
case "INFO":
case "DEBUG":
System.out.println("通常ログ");
break;
case "WARN":
case "ERROR":
System.out.println("重要ログ");
break;
default:
System.out.println("未知のログレベル");
}
Java👉 「INFO」「DEBUG」をまとめて通常ログ、「WARN」「ERROR」をまとめて重要ログにするためにフォールスルーを使っています。
戦略パターンによるリファクタ解答
1. 戦略インターフェース
interface LogStrategy {
void log(String message);
}
Java2. 具体的な戦略クラス
class NormalLogStrategy implements LogStrategy {
public void log(String message) {
System.out.println("通常ログ: " + message);
}
}
class ImportantLogStrategy implements LogStrategy {
public void log(String message) {
System.out.println("重要ログ: " + message);
}
}
class UnknownLogStrategy implements LogStrategy {
public void log(String message) {
System.out.println("未知のログレベル: " + message);
}
}
Java3. コンテキスト(戦略選択)
import java.util.HashMap;
import java.util.Map;
class LogContext {
private static final Map<String, LogStrategy> strategies = new HashMap<>();
static {
// 通常ロググループ
strategies.put("INFO", new NormalLogStrategy());
strategies.put("DEBUG", new NormalLogStrategy());
// 重要ロググループ
strategies.put("WARN", new ImportantLogStrategy());
strategies.put("ERROR", new ImportantLogStrategy());
}
public static void execute(String level, String message) {
LogStrategy strategy = strategies.getOrDefault(level, new UnknownLogStrategy());
strategy.log(message);
}
}
Java4. 利用側
public class Main {
public static void main(String[] args) {
LogContext.execute("INFO", "通常ログのテスト"); // 通常ログ: 通常ログのテスト
LogContext.execute("ERROR", "エラーログのテスト"); // 重要ログ: エラーログのテスト
LogContext.execute("UNKNOWN", "未知ログのテスト"); // 未知のログレベル: 未知ログのテスト
}
}
Java解説
- switchのフォールスルーを排除
→ Mapに「ログレベル」と「戦略クラス」を紐付けることで安全に分類。 - メリット
- フォールスルーの危険がなくなる。
- 新しいログレベルを追加する場合はMapに登録するだけ。
- 各戦略クラスを単体テスト可能。
- デメリット
- クラス数が増えるので小規模な処理には冗長。
- ただし業務コードでは「責務分離」「拡張性」が重要なので有効。
まとめ
- フォールスルーを使わずに「複数条件をまとめる」には、戦略パターン+Map登録が有効。
- ログレベル出力のような「グループ化された条件分岐」に適している。
👉 ここまでで「季節判定」「HTTPステータス分類」「ユーザー権限判定」「ログレベル出力」をすべて戦略パターンに置き換えました。


