ストラテジーパターンというGoFのデザインパターンが良いコード悪いコードでも紹介されていたので、素振りします。
自分の言葉で上手な言語化ができていないので、メリットは参考情報や良いコード悪いコードの購入、または別の方の記事を参考にしてください。
環境
- Java
- 17
今回の処理
複数の言語の文章を、ひとつの言語に変換する。
※ 変換の具体的なロジックは実装しない。
対応
文章と言語名が記載されたDTOを生成する。
@Data public class Question { private String sentence; private Locale locale; }
ストラテジーパターンを使用しやすいように、FCCを使用してQuestionのリストを用意し、LocaleをKeyとしたMap型に変換する。
@Data @Builder public class QuestionList { List<Question> value; public Map<Locale, List<Question>> groupByLocale() { return value.stream() .collect(Collectors.groupingBy( Question::getLocale )); } }
翻訳用のinterfaceを用意する。
public interface Translator { List<Question> translate(List<Question> question); }
interfaceを継承した翻訳クラスを用意する。
public class FromEnToJa implements Translator { @Override public List<Question> translate(List<Question> question) { return question.stream() .map(e -> e.toBuilder().locale(Locale.JAPANESE).build() ).collect(Collectors.toList()); } } public class FromFrToJa implements Translator { @Override public List<Question> translate(List<Question> question) { return question.stream() .map(e -> e.toBuilder().locale(Locale.JAPANESE).build() ).collect(Collectors.toList()); } } public class NoopTransrate implements Translator { @Override public List<Question> translate(List<Question> question) { return question; } }
LocaleをKeyとし、実際に処理するクラスをvalueとしたMapを用意する。
private final Map<Locale, Translator> toJaActionMap = Map.of( Locale.ENGLISH, new FromEnToJa(), Locale.JAPANESE, new NoopTransrate(), Locale.FRENCH, new FromFrToJa() );
文章とLocaleを元に、すべてを日本語に変換する処理をする。
public QuestionList translate() { final List<Question> list = new ArrayList<>(); // 処理を移譲しているので、中身が違う翻訳処理を行う。 this.groupByLocale().forEach( (key, value) -> list.addAll(toJaActionMap.get(key).translate(value)) ); return new QuestionList(list); }
ソースコード
- https://github.com/hirotoKirimaru/cucumber-sample/blob/a3e62238eea16ebbdfb8e9c4a1d9b4c24fd92c58/kirimaru-core/src/main/java/kirimaru/biz/domain/Question.java
- https://github.com/hirotoKirimaru/cucumber-sample/blob/a3e62238eea16ebbdfb8e9c4a1d9b4c24fd92c58/kirimaru-core/src/main/java/kirimaru/biz/domain/QuestionList.java
- https://github.com/hirotoKirimaru/cucumber-sample/blob/a3e62238eea16ebbdfb8e9c4a1d9b4c24fd92c58/kirimaru-core/src/test/java/kirimaru/biz/domain/StrategyPatternTest.java
終わりに
正直、今回の例示とした委譲処理はメリット薄いです。ただ、ストラテジーパターンを素振りしておくことで、見通しの悪い処理を切り出せるという意識を持っておきたいです。
地味ながら、JavaGoldで勉強したBiConsumerを使うタイミングが分かっていなかったので、今回のストラテジーパターンを素振りすることで使用できてよかったです。
// ここが内部的にはBiConsumerで処理されています。 this.groupByLocale().forEach( (key, value) -> list.addAll(toJaActionMap.get(key).translate(value)) );