LoginSignup
1
0

More than 5 years have passed since last update.

Chain of ResponsibilityパターンのScalaによる実装サンプル

Posted at

JJUGナイトセミナーで紹介されていた(私は出席してないので伝聞) Chain of Responsibility をJavaのラムダとSteram APIで実装する サンプル を見て思ったのは、Javaだとやっぱり記述が冗長になってしまうなーという点。

ということで、上記サンプルと同じことをScalaでやってみた。

まずはFileクラスの定義:

File.scala
sealed abstract class File(val content: String)
case class Text(c: String) extends File(c)
case class Presentation(c: String) extends File(c)
case class Audio(c: String) extends File(c)
case class Video(c: String) extends File(c)

CoRを構成する個々のハンドラを表すトレイト:
--> メソッドは、自分が処理できない場合に次のハンドラに処理を委譲する、合成された Handler を生成するもの。

Handler.scala
trait Handler {
  def handle(file: File): Option[String]

  def -->(next: Handler): Handler = file => {
    val result = this.handle(file)
    result match {
      case Some(s) => Some(s)
      case None => next.handle(file)
    }
  }
}

使用例:
CoRを h1 --> h2 --> h3 --> h4 と視覚的に表現できるのがうれしい。

ChainOfRespTest.scala
import org.scalatest._
import org.scalatest.Matchers._

class ChainOfRespTest extends FunSuite with Matchers {

    test("Chain of Responsibility works fine") {
      val h1: Handler = _ match {
        case Text(c) => Some("Text file: " + c)
        case _ => None
      }
      val h2: Handler = _ match {
        case Presentation(c) => Some("Presentation file: " + c)
        case _ => None
      }
      val h3: Handler = _ match {
        case Audio(c) => Some("Audio file: " + c)
        case _ => None
      }
      val h4: Handler = _ match {
        case Video(c) => Some("Video file: " + c)
        case _ => None
      }
      val result = h1 --> h2 --> h3 --> h4 handle Audio("Blackout")

      result should be (Some("Audio file: Blackout"))
    }
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0