FizzBuzz

初めて書いたアルゴリズムがFizzBuzzでした

Template Methodパターンを使ったのでまとめる

Template Methodパターンとは

Template Methodパターンは、抽象クラスとその派生クラスを使うデザインパターン

実装手順

Template Methodパターンの実装手順は以下のようになる。

  • 基本クラスに汎用的なアルゴリズムを実装する
  • 派生クラスで実装してほしいメソッドを抽象メソッドとして定義する
  • 派生クラスで基本クラスの抽象メソッドを実装する

実装例

Template Methodパターンの実装例を考えた。 具体的な実装というよりは、こんな感じで実装できそうだという感じ。

複数媒体をスクレイピングするケースを考える。 媒体に関わらずやりたいことは、「URLにアクセスし、記事のタイトルを取得して何らかの処理をしたい」というユースケースで考えた。 抽象クラスはこのようにしてみた。

コメントアウトの部分は、こういう処理が本当なら実装されるというものを表している。 処理の説明などではない。

abstract class Scraping {
  constructor(private baseURL: string) {}
  execute() {
    /**
     * 共通のスクレイピング処理を実装する
     * URLにアクセスするところなど
     */

    const urls = this.getArticleURLs(this.baseURL)

    const titles = urls.map((url, _) => this.extractTitle(url))

    /**
     * titlesを使った処理
     * 記事のタイトルを出力したりするなど
     */
  }

  abstract getArticleURLs(baseURL: string): string[]

  abstract extractTitle(articleURL: string): string
}

export default Scraping

解説

Scrapingクラスという抽象クラスをTemplateMethodパターンのクラスとして定義する。

executeメソッドは実行するための処理を表している。 どの媒体をスクレイピングするにしても、変わらない処理を実装している。 具体的には、以下のような流れで処理を行う想定。

  1. URLを元にサイトを見に行く
  2. サイトにある記事ごとのURLを取得する
  3. 記事ごとのURLにアクセスし、タイトルを取得する
  4. 3で取得したタイトルを使って何らかの処理をする

次に、抽象メソッドとしてgetArticleURLsメソッドextractTitleメソッドを定義している。

getArticleURLsメソッドは記事ごとのURLを取得するためのメソッド。 媒体ごとに記事のURLの取得方法は違うはずなので、Scrapingクラスを継承したサブクラスで実装することにする。 求人サイトをスクレイピングすると仮定するとWantedlyScrapingやGreenScrapingというサブクラスでWantedlyやGreenの求人のURLを取得する方法は異なるので、それぞれに実装する。

extractTitleメソッドは、記事からタイトルを取得するメソッド。 タイトルも媒体ごとに取得方法がことなるので、サブクラスで実装する。

このように実装することで、共通する処理は抽象クラスに実装し、詳細がことなるメソッドはサブクラスで実装することができるようになる。

注意点

Template Methodパターンには、「派生クラスでは基本クラスに宣言されている抽象メソッドだけを使って実装する」というルールがある。 そのため、サブクラスにしかないパブリックなメソッドを実装してはいけない。

参照

qiita.com