有限オートマトン
Acca Actorでは、有限オートマトン(finite state machine)と呼ばれる振る舞いのモデルを用いることができる。
また、これを実装しやすくするために、FSMというトレイトが用意されている。(自ら実装してもよい)
ただし、有限オートマトンはAkka(Actor)がなくても成立する概念なので、
Actorの要素を取り除き、シンプルな有限オートマトンを実装して説明する。
有限オートマトン(wikipedia)
https://ja.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E3%82%AA%E3%83%BC%E3%83%88%E3%83%9E%E3%83%88%E3%83%B3#UML%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%9E%E3%82%B7%E3%83%B3
有限オートマトン(finite state machine)を単純化して考える
State.Scala
/** 状態 */
sealed trait State{
/** 振る舞い */
type Behavior = Command => State
/** 状態名 */
val stateName: String
/** 次の状態(コマンド→状態変換の振る舞い) */
val getNextState : Behavior
}
/** 最終状態(もう状態変化が起こらない状態) */
sealed trait FinalState extends State {
/** 次の状態(どのコマンドが来ても、今の状態に等しくなる) */
override final val getNextState : Behavior = {
case StartProcess => this
case ProcessFinishSafety => this
}
}
case object WaitingForRequest extends State {
override val stateName: String = "WaitingForRequest"
override val getNextState : Behavior = {
case StartProcess => Processing
case ProcessFinishSafety => Terminated
}
}
case object Processing extends State {
override val stateName: String = "Processing"
override val getNextState : Behavior = {
case StartProcess => Terminated
case ProcessFinishSafety => Finished
}
}
case object Finished extends FinalState {
override val stateName: String = "Finished"
}
case object Terminated extends FinalState {
override val stateName: String = "Terminated"
}
Command.Scala
/** コマンド */
sealed trait Command
/** 処理を開始させるコマンド */
case object StartProcess extends Command
/** 処理中に安全に終了させるコマンド */
case object ProcessFinishSafety extends Command
FakeActor.Scala
import java.util.Objects
/** AkkaActor要素を取り除いた有限状態マシン。Akka Actorを使用する場合は、この部分が実際のActorとなる。 */
final class FakeActor(){
/** 状態(初期状態) */
private var state : State = WaitingForRequest
/** 状態の確認 */
def getState : String = state.stateName
/**
* コマンドを送信して、状態を変更する
* @param command コマンド
* @return 結果、状態が変動するか
*/
def goNextState(command: Command): Boolean = {
val next: State = state.getNextState(command)
val changed: Boolean = !Objects.equals(state,next)
state = next
changed
}
}
Applicationからの利用
trait.Scala
object Application extends App {
System.out.println("-------SUCCESS--------")
val success = FakeActor()
System.out.println(success.getState)
System.out.println("changed:" + success.goNextState(StartProcess))
System.out.println(success.getState)
System.out.println("changed:" + success.goNextState(ProcessFinishSafety))
System.out.println(success.getState)
System.out.println("changed:" + success.goNextState(StartProcess))
System.out.println(success.getState)
System.out.println("-------FAILED--------")
val failed = FakeActor()
System.out.println(failed.getState)
System.out.println("changed:" + failed.goNextState(ProcessFinishSafety))
System.out.println(failed.getState)
System.out.println("changed:" + failed.goNextState(StartProcess))
System.out.println(failed.getState)
}