Skip to content

Flyweight パターンの Scala での実装例

Posted on:2010年12月30日 at 13:20

重たい処理の結果をキャッシュして、無駄な処理を行わないようにする実装パターン。GoF による 23 のデザインパターンでは、Flyweight パターンと呼ばれている。

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

このパターンを使うメリットは、

というところ。注意点としては、

Flyweight パターンの登場人物は、

の 3 者となり、以下の例では、Flyweight -> Stamp、FlyweightFactory -> StampFactory、Client -> FlyweightPatternExample となる。

import scala.collection.mutable

// Flyweight
class Stamp(t: Char) {
  def print = System.out.print(t)
}

// FlyweightFactory
object StampFactory {
  val pool = mutable.Map.empty[Char, Stamp]

  def get(t: Char): Stamp = pool.get(t) match {
    case Some(s: Stamp) => s
    case None =>
      val stamp = createStamp(t)
      pool += (t -> stamp)
      stamp
  }

  private def createStamp(t: Char): Stamp = {
    Thread.sleep(1000) // 実は重たい処理。。
    new Stamp(t)
  }
}

// Client
object FlyweightPatternExample {
  def main(args: Array[String]) = {
    val stamps = mutable.ArrayBuffer.empty[Stamp]

    val chars = "たかいたけたてかけた".toCharArray

    println("-" * 5 + " collecting ...")
    chars.foreach { c =>
      val start = System.nanoTime
      stamps += StampFactory.get(c)
      val end = System.nanoTime
      println("'%s' (%d)".format(c, end - start))
     }

    println("-" * 5 + " output")
    stamps.foreach { e =>
      e.print
      println(" " + e.toString)
    }
  }
}

実行結果は以下の通り。

[info] Running FlyweightPatternExample
----- collecting ...
'た' (1002272250)
'か' (1000112222)
'い' (1000181113)
'た' (73671)
'け' (1000181459)
'た' (8248)
'て' (1000120234)
'か' (7799)
'け' (5361)
'た' (5243)
----- output
Stamp@11c537f
Stamp@adcae8
Stamp@1e4605c
Stamp@11c537f
Stamp@727896
Stamp@11c537f
Stamp@14ace71
Stamp@adcae8
Stamp@727896
Stamp@11c537f

上記の結果から、

という点がわかる。