Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 阿克卡的战略模式_Scala_Design Patterns_Akka - Fatal编程技术网

Scala 阿克卡的战略模式

Scala 阿克卡的战略模式,scala,design-patterns,akka,Scala,Design Patterns,Akka,这是我上一个问题的继续 我有10种类型的事件,它们是从我需要处理的事件扩展而来的 我想在单独的trait中为每个事件实现业务逻辑,因为混合所有10个事件处理程序函数将产生数百(如果不是数千)行代码 我不想为每个事件创建不同的演员类型。例如: class Event1Actor extend Actor{ def receive ={ case Event1(e) => //event1 Business Logic } } class Event2Actor exte

这是我上一个问题的继续

我有10种类型的事件,它们是从我需要处理的事件扩展而来的

我想在单独的trait中为每个事件实现业务逻辑,因为混合所有10个事件处理程序函数将产生数百(如果不是数千)行代码

我不想为每个事件创建不同的演员类型。例如:

class Event1Actor extend Actor{
  def receive ={
     case Event1(e) => //event1 Business Logic
   }
}

class Event2Actor extend Actor{
  def receive ={
     case Event2(e) => //event2 Business Logic
   }
}  
同样的事件3参与者,事件4参与者,等等

这样的代码对我来说很难看,因为我需要在每个参与者内部实现业务逻辑

实现10个不同的特性和10个不同的演员类似乎也是糟糕的设计

我正在寻找基于设计模式的某种通用解决方案,例如strategy模式。

案例类EventOperation[T eventType.execute
case class EventOperation[T <: Event](eventType: T)

class OperationActor extends Actor {

  def receive = {
    case EventOperation(eventType) => eventType.execute
  }

}

trait Event {
 def execute //implement execute in specific event class
}

class Event1 extends Event {/*execute implemented with business logic*/}
class Event2 extends Event {/*execute implemented with business logic*/}
} } 特质事件{ def execute//在特定事件类中执行 } 类Event1扩展了事件{/*execute,该事件由业务逻辑*/}实现 类Event2扩展了事件{/*execute,该事件由业务逻辑*/}实现

希望这就是您想要的并对您有所帮助,我已使用此模式删除了多余的参与者,这些参与者将所有操作包装在一个执行不同类型事件的参与者之下。

您可以尝试类似的方法,包括通过基本特征自动组合接收功能。首先,代码:

case class Event1(s:String)
case class Event2(i:Int)
case class Event3(f:Float)

trait EventHandlingActor extends Actor{
  var handlers:List[Receive] = List.empty

  override def preStart = {
    val composedReceive = handlers.foldLeft(receive)((r,h) => r.orElse(h))
    context.become(composedReceive)
  }

  def addHandler(r:Receive) {
    handlers = r :: handlers
  }

  def receive = PartialFunction.empty[Any,Unit]
}

trait Event1Handling{ me:EventHandlingActor =>
  addHandler{
    case Event1(s) => println(s"${self.path.name} handling event1: $s") 
  }
}

trait Event2Handling{ me:EventHandlingActor =>
  addHandler{
    case Event2(i) => println(s"${self.path.name} handling event2: $i") 
  }
}

trait Event3Handling{ me:EventHandlingActor =>
  addHandler{
    case Event3(f) => println(s"${self.path.name} handling event3: $f") 
  }
}
因此,您可以在
EventHandlingActor
trait中看到,我们设置了一个
Receive
类型的
List
,可以通过我们堆叠到具体actor中的每个特定处理特征添加到该列表中。然后,您可以看到在调用
addHandl的单独特征中定义的每个事件的处理功能的定义er
添加另一项处理功能。在
启动前
中,对于任何类型的
事件处理参与者
impl,接收函数将与
接收
一起组成,作为起点(默认为空),然后将接收impl与
上下文热交换。变为

现在以几个impl参与者为例:

class MyEventHandlingActor extends EventHandlingActor 
  with Event1Handling with Event2Handling with Event3Handling

case class SomeOtherMessage(s:String)
class MyOtherEventHandlingActor extends EventHandlingActor with Event1Handling{
  override def receive = {
    case SomeOtherMessage(s) => println(s"otherHandler handling some other message: $s")
  } 
}
第一个类只处理事件,所以它所需要做的就是定义它处理哪些事件,并在适当的特征中混合。第二个类处理一种类型的事件,但也处理一些其他非事件的消息。此类重写默认的空接收,并提供处理非事件消息的功能

如果我们像这样测试代码:

  val system = ActorSystem("test")
  val handler = system.actorOf(Props[MyEventHandlingActor], "handler")

  handler ! Event1("foo")
  handler ! Event2(123)
  handler ! Event3(123.456f)

  val otherHandler = system.actorOf(Props[MyOtherEventHandlingActor], "otherHandler")
  otherHandler ! Event1("bar")
  otherHandler ! SomeOtherMessage("baz")
然后,我们将看到类似的输出(由于消息的异步处理,顺序发生了变化):


即使对于简单的应用程序,擦除也是一个问题……而且它可能非常棘手(甚至不可能)在某些情况下。使用Akka…它涉及序列化和网络…我建议…尝试更改设计。这是一个确切的问题,如何更改设计?我仍然有10种类型的消息,不能更改。更改它以便不需要类型参数…为每种类型参数创建类。换句话说…使用代数类型。.:)。就像@DAR在下面的回答中建议的那样。你考虑过代理而不是actors吗?Actor.Receive是PartialFunction[Any,Unit]的类型别名部分功能有.orElse方法来组合它们。我真的不明白你想要实现什么,但我建议你先看看功能组合,然后看看可堆叠的特性。
otherHandler handling event1: bar
handler handling event1: foo
handler handling event2: 123
handler handling event3: 123.456