Scalaで今更GoFのデザインパターンを書いてみた

Scala Advent Calender 2014の記事です。遅れてすみません。

デザインパターンをScalaで書いてみるとどうなるか？ということで、今更ですがGoFのデザインパターンをScalaで書いてみました。デザインパターンについての説明は他の人にお任せしますw

[Wikipedia](http://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3_%28%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%29)
に載っている順に紹介していきます。なかには、流石Scalaといったのもありますが、Javaとかとあまり変わらないのもあります。


## AbstractFacotry

Javaとかとほとんど変わりません。

```scala
trait AbstractFactory{
  def createA() : A
  def createB() : B
  def createC() : C
}

class ConcreteFactory extends AbstractFactory{

  def createA() : A = ...
  def createB() : B = ...
  def createC() : C = ...
}
```

## Builder

自己タイプを使うことで、実装先でメソッドを追加したときに便利にできます。

```scala

trait Builder{ self =>
  
  def withA(a : A) : self.type
  def withB(b : B) : self.type
  def build() : T

}

class ConcreteBuilder extends Builder{
  def withA(a : A) = { ...; this}
  def withB(b : B) = { ...; this}
  def withC(c : C) = { ...; this}
  def build() = ...
}

new ConcureteBuilder().withA(a).withC(c).build()
```

## FactoryMethod

traitが実装を持てるので、簡単に様々な組み合わせがつくれます。

```scala

trait FactoryMethodUser{

  def doAction() = {
    val product = createProduct()
    product.use()
  }
  def createProduct() : Product
}

trait AFactory{ self : FactoryMethodUser =>
  def createProduct() = new ProductA()
}
trait BFactory{ self : FactoryMethodUser =>
  def createProduct() = new ProductB()
}

object ForA extends FactoryMethodUser with AFactory
object ForB extends FactoryMethodUser with BFactory
```

## Prototype

case classで一撃。(ただし、コピーしたい変数は全てコンストラクタに書く必要あり

```
case class Proto(a : Int, b : String, c : Double)

val proto = Proto(1,"aaa",2.4)

val copied = proto.copy()
```

## Singleton

objectはSingletonです。

```
object Singleton
```

## Adapter

Javaとあまり変わらず。

```scala

class A{
  def name : String = ...
}
class B{
  def namae : String = ...
}

trait NameAdapter{
  def name : String
}

class AAdapter(a : A) extends NameAdapter{
  def name = a.name
}
class BAdapter(b : B) extends NameAdapter{
  def name = b.namae
}
```

## Bridge

Javaとあまり変わらず。

```scala

trait Abstraction{
  def implementor : Implementor
}

trait Implementor{
}


case class RefinedAbstraction(implementor : Implementor) extends Abstraction
class RefinedImplementor() extends Implementor
```

## Composite

Javaとあまり変わらず。

```scala
trait Component{
  def operation() : T
}

class Leaf extends Component {
  def operation() : T = ...
}

class Composite extends Component {
  def operation() : T = ...
  def add(child : Component) = ...
}
```

## Decorator

abstract traitを使用することでデコりたい機能だけを分離実装可能

```

trait DecoratedObject{
  def funcA()
}

class ImplA extends DecoratedObject{
  def funcA() = ...
}
class ImplB extends DecoratedObject{
  def funcA() = ...
}

trait LoggingDecorator{
  abstract override def funcA() = {
    print("Logging")
    super.funcA()
  }
}

class DecoratedA extends ImplA with LoggingDecorator
class DecoratedB extends ImplB with LoggingDecorator
```

## Facade

Javaと変わらず

```scala

class Facade(a : A){
  def walk(speed : Int) = {
    a.goFront(speed)
  }
}
```

## Flyweight

mutableMap使うと楽

```scala
import scala.collection.mutable.Map

class FlyWeight{
  val map = Map.empty[String,HeavyObject]
  
  def get(key : String) = {
    map.getOrElse(key,{
      createHeavyObject(key)
    })
  }
}
```
また、ConcurrentHashMapを使うと非同期対応も楽々できます。


## Proxy

implicit conversionを使ったテクニックで楽にかけます。

```scala

case class User(name : String, age: Int)

object ProxyUser{
  implicit def toUser(pu : ProxyUser) = pu.user
}
case class ProxyUser(user : User){
  def name = "Mr." + user.name
}

val proxy = ProxyUser(User("Tom",20))

println(proxy.name) // "Mr.Tom"
println(proxy.age)  // "20"
```

## Chain of Responsibility

PartialFunctionで実装できます。

```scala
val responsibility1 : PartialFunction[String,Unit] = {
  case "Hello" => println("Hello world")
  case "こんにちは" => println("こんにちは世界")
}

val responsibility2 : PartialFunction[String,Unit] = {
  case "你好" => println("你好世界")
}

val chain = responsibility1 orElse responsibility2

println(chain("Hello")) // "Hello world"
println(chain("你好")) // "你好世界"
```

## Command

もう関数で良くね？

```scala

val command1 = (s : String) => println(s)
val command2 = (s : String) => println(s + s)

val commands = List(command1,command2)

commands.foreach( _("hoge"))

```

## Interpreter

ParserCombinator使えばいいと思うよ！ここには書ききれないので[ここ](http://seratch.hatenablog.jp/entry/20111010/1318254084)とか見てください。

## Iterator

もう、当たり前過ぎてこれデザインパターンか？ってレベル

```scala
for(i <- 0 until 100){
  println(i)
}

```

## Mediator

Javaと変わらないので割愛

## Memento

immutableに実装すればだいたい同じことできます。sbtみたいな感じ。

```
case class Memento(state1 : Int , state2 : String){
  def withState1( s : Int) = this.copy(state1 = s)
}

val first = Memento(1,"hoge")
val memo = first.withState1(2).copy(state2 = "aaa")
val last = memo.copy(state1 = 4,state2 = "cccc")

print(memo) // "Memento(2,"aaa")"
```


## Observer

記号メソッドを使えるので、C#のeventみたいにいい感じにかけます。

```scala

class Subject{
  val event = new Event
  def fireEvent() = event.trigger("hoge")
}

class Event{
  private var handlers : List[String => Any] = Nil
  def +=( handler : String => Any) = handlers = handlers :+ handler
  def trigger(v : String) = handlers.foreach(_(v))
}
var subject = new Subject()
subject.event += s => println(s)
subject.event += s => if(s.startsWith("h")) println("のび太さんのH")

subject.fireEvent()

```

## State

Javaと大差ないので割愛。
むしろ、Mutableな実装になりやすいのでScalaではあまり使いたくないパティーン


## Strategy

traitで実現できます。
または、implicitパラメーターも有りかと

```scala
trait Strategy{
  def execute()
}

trait StrategyA extends Strategy{
  def execute() = ...
}
trait StrategyB extends Strategy{
  def execute() = ...
}

trait Action{ self : Strategy =>
  def action() = {
    execute()
  }
}
  
val a = new Action with StrategyA
a.action()
val b = new Action with StrategyB
b.action()
```

implicit parameterだと

```scala
trait Strategy{
  def execute()
}

class StrategyA extends Strategy{
  def execute() = ...
}
class StrategyB extends Strategy{
  def execute() = ...
}

class Action{
  def action()(implicit strategy : Strategy) = {
    strategry.execute()
  }
}

{
  implicit val strategy = new StrategyA
  val action = new Action()
  action.action()
}

{
  implicit val strategy = new StrategyB
  val action = new Action()
  action.action()
}

```


## TemplateMethod

traitのmixinを使うことで、機能を小分けにしやすいです。

```scala
trait Base { self : FuncA with FuncB => {
  def work() = {
    val v = doA()
    val result = doB(v)
    result
  }
}

trait FuncA{
  def doA() : String
}
trait FuncB{
  def doB(s : String) : Int
}

object Imple1_1 extends Base with FuncAImpl1 with FuncBImpl1
object Imple1_2 extends Base with FuncAImpl1 with FuncBImpl2
object Imple2_1 extends Base with FuncAImpl2 with FuncBImpl1

```


## Visitor

Javaと変わらず。むしろ、わりと避けるべきデザインパターン。

# 総括

途中力尽きたところもありましたが、Scalaでデザパタを一通り実装してみました。
是非みなさんもデザインパターンを学んで、ウンコードを撲滅しましょう。