Factory Method パターンの Scala での実装例 (プラス Strategy も)

Written by @dr_taka_n at 2011/01/03 13:01 []

Wikipedia にある 23 のデザインパターン(デザインパターン (ソフトウェア) - Wikipedia)の Java のサンプルを Scala で書いてみる第2弾。

今回は、クラスの選択の決定をサブクラスに委ねる実装パターン。 GoF による 23 のデザインパターンでは、Factory Method パターンと呼ばれているもの。

上記 Wikipedia に Java での実装例があるが、これを Scala で実装してみる。

Factory Method パターンの登場人物は、

  • Creator
    ConcreteCreator
  • Product
    ConcreteProduct

となる。

// FactoryMethod Pattern
// Creator
abstract class ListPrinter {
  def printList(list: List[String]) {
    val comparator = createComparator
    list.sortWith(comparator).foreach(println)
  }
  // factoryMethod
  protected def createComparator: (String, String) => Boolean
}

// Function2[String, String, Boolean] が product に相当
// ConcreteCreator
class DictionaryOrderListPrinter extends ListPrinter {
  override protected def createComparator: (String, String) => Boolean =
    (s1, s2) => s1 < s2  // ConcreteProduct
}

// ConcreteCreator
class LengthOrderListPrintter extends ListPrinter {
  override protected def createComparator: (String, String) => Boolean =
    (s1, s2) => s1.size < s2.size  // ConcreteProduct
}

object FactoryMethodPatternExampleWiki {
  def main(args: Array[String]) = {
    val strs = List("いちご", "もも", "いちじく")
    println("五十音順で表示:")
    (new DictionaryOrderListPrinter).printList(strs)
    println("長さ順で表示:")
    (new LengthOrderListPrintter).printList(strs)
  }
}

実行結果は以下の通り。

[info] Running FactoryMethodPatternExampleWiki 
五十音順で表示:
いちご
いちじく
もも
長さ順で表示:
もも
いちご
いちじく

ちょっと無理やり感があって、何ともしっくりこない。。例示のサンプルがあまりよくないのかな・・・

上記の取り上げられている例への解法であれば、Factory Method パターンより、Strategy パターンの方がしっくりくる。

// Strategy Pattern
class ListPrinter(comparator: (String, String) => Boolean) {
  def printList(list: List[String]) {
    list.sortWith(comparator).foreach(println)
  }
}

object StrategyPatternExampleWiki {
  def main(args: Array[String]) = {
    val strs = List("いちご", "もも", "いちじく")
    println("五十音順で表示:")
    (new ListPrinter((s1, s2) => s1 < s2)).printList(strs)
    println("長さ順で表示:")
    (new ListPrinter((s1, s2) => s1.size < s2.size)).printList(strs)
  }
}

実行結果は以下の通り。

[info] Running StrategyPatternExampleWiki 
五十音順で表示:
いちご
いちじく
もも
長さ順で表示:
もも
いちご
いちじく
blog comments powered by Disqus