エキサイト株式会社エンジニアの佐々木です。エキサイトHDアドベントカレンダー2024の8日目を担当します。
メディア事業部ではJavaを使用しており、理由はいくつかありますがLambda式が書けるというのは1つの理由になっているかと思います。ストラテジーパターンはアプリケーションコードを書くうえでも便利なものなので、ぜひすぐに使えるようにしましょう。
ストラテジーパターンとは?
ストラテジーパターンは、ある処理のアルゴリズムを、その処理を使う部分から切り離し、交換できるようにするデザインパターンです。簡単にいうと、アルゴリズムを適用する際に前条件のようなものを使用時に決められます。
下記のようなデータがあります。記事に対して、カテゴリやPV、タグなどが設定されているようなデータあります。
@Getter @RequiredArgsConstructor static class Article { private final String title; private final String category; private final List<String> tags; private final int pv; } List<Article> articleList = List.of( new Article("title1", "text", List.of("tag1", "tag2", "tag10"), 100), new Article("title2", "comic", List.of("tag2", "tag3"), 200), new Article("title3", "video", List.of("tag3", "tag4"), 300), new Article("title4", "text", List.of("tag4", "tag5"), 400), new Article("title5", "comic", List.of("tag5", "tag6"), 500), new Article("title6", "photo", List.of("tag6", "tag7"), 600), new Article("title7", "comic", List.of("tag7", "tag8"), 700), new Article("title8", "text", List.of("tag8", "tag9"), 800), new Article("title9", "photo", List.of("tag9", "tag10", "tag2"), 900), new Article("title10", "comic", List.of("tag10", "tag1"), 1000) );
ストラテジーパターンを使わない場合
上記のデータを色々なカテゴリやタグごとでPVの集計をしたいとします。通常はそれっぽい別々のコードを書いたり、Switchが登場したりするかなと思います。
// テキストカテゴリを集計するメソッド private int totalPvText(List<Article> articleList) { return articleList.stream() .filter(article -> "comic".equals(article.getCategory())) .mapToInt(e -> e.getPv()) .sum(); } // コミックカテゴリを集計するメソッド private static int totalPvComic(List<Article> articleList) { return articleList.stream() .filter(article -> "comic".equals(article.getCategory())) .mapToInt(e -> e.getPv()) .sum(); }
ストラテジーパターンを使用する場合
ストラテジーパターンを使用すると、下記のような実装になります。
private int totalPv(List<Article> articleList, Predicate<Article> articlePredicate) { return articleList.stream() .filter(articlePredicate) .mapToInt(e -> e.getPv()) .sum(); }
articlePredicate
という引数を取るように変更して、それをstreamのfilter
に設定します。これで、メソッドの外から絞り込み条件を指定することが可能になります。
// コミックカテゴリの場合 totalPv(articleList, article -> article.getCategory().equals("comic")); // テキストカテゴリの場合 totalPv(articleList, article -> article.getCategory().equals("text")); // tag1を含んでいる場合 totalPv(articleList, article -> article.getTags().contains("tag1")); // 全カテゴリの場合 totalPv(articleList, article -> true);
上記のように専用に用意しなくても呼び出す側が決めることが可能になります。
まとめ
ストラテジーパターンは、関数型が取り入れられているプログラミング言語であれば割と簡単に使用できると思います。完結になりますし、バグも抑えられますし、テストも簡単ですので、ぜひ導入してみてください、
最後に
エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。
募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com