become / unbecome

Einstieg
Beispiel

Einstieg

Bis jetzt haben wir auf Nachrichten immer mit receive reagiert. Manchmal möchten wir jedoch auf Nachrichten unterschiedlich reagieren. Eine Möglichkeit das zu Realisieren ist, in den einzelnen cases entsprechende Kontrollstrukturen einzubauen.

Wir brauchen sicher nicht viel Fantasie, um uns vorzustellen, wie schnell die receive Methode unübersichtlich wird und aus Spaghetti-Code besteht.

Abhilfe schaffen hier die Methoden become und unbecom des zugehörigen ActorContext. Die Methode become erwartet als Argument eine Methode (Funktion), welche mit der receive Methode kompatibel ist. Von diesem Zeitpunkt an werden die zu bearbeitenden Nachrichten von der neuen Methode abgearbeitet. Auch in der neuen Bearbeitungsmethode können wir die aktuelle Bearbeitungsmethode mit become neu zuweisen.

Möchten wir den initialen Zustand wieder herstellen, können wir die unbecome Methode des ActorContext aufrufen. Diese Methode stellt den ursprünglichen (initialen) Zustand wieder her, unabhängig davon, wie oft das Verhalten mit become verändert wurde.

Das nachfolgende Beispiel zeigt die Verwendung von become und unbecome.

Beispiel

import akka.actor._

case class SimpleMessage(s: String)
case object DoBecomeNewReceiver
case object DoUnbecome

object MyApplication {
  def main(args: Array[String]) {
    val system = ActorSystem("Main")
    val ac = system.actorOf(Props(classOf[MyActor]))
    
    ac ! SimpleMessage("Hi!")
    ac ! DoBecomeNewReceiver
    ac ! SimpleMessage("Ho!")
    ac ! DoBecomeNewReceiver
    ac ! SimpleMessage("Jo.")
    ac ! DoUnbecome
    ac ! SimpleMessage("How are you?")
    
    Thread.sleep(1000)    
    sys.exit(0)
  }
}

class MyActor extends Actor {

  def receive = {
    case SimpleMessage(s) => println("Initial: "+s)
    case DoBecomeNewReceiver => context become receiveA    
  }
  
  def receiveA: Receive = {
    case SimpleMessage(s) => println("receiveA: "+s)
    case DoBecomeNewReceiver => context become receiveB
    case DoUnbecome => context unbecome
  }
  
  def receiveB: Receive = {
    case SimpleMessage(s) => println("receiveB: "+s)
    case DoUnbecome => context unbecome
  }
}

itmapa.de - X2H V 0.21

Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:

Initial: Hi!
receiveA: Ho!
receiveB: Jo.
Initial: How are you?