Akka 中的策略模式
Strategy pattern in Akka
这是我之前问题的延续
我有 10 种类型的事件,这些事件是我需要处理的事件的扩展。
我想在单独的特征中为每个事件实现业务逻辑,因为混合所有 10 个事件处理函数将产生数百(如果不是数千)行代码。
我不想为每个事件创建不同的 Actor 类型。例如:
class Event1Actor extend Actor{
def receive ={
case Event1(e) => //event1 Business Logic
}
}
class Event2Actor extend Actor{
def receive ={
case Event2(e) => //event2 Business Logic
}
}
以及相同的 Event3Actor、Event4Actor 等....
这样的代码在我看来很难看,因为我需要在每个 Actor 内部实现业务逻辑。
实现 10 个不同的特征和 10 个不同的 Actor 类 似乎也是糟糕的设计。
我正在寻找某种基于设计模式的通用解决方案,例如策略模式。
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*/}
希望这就是您正在寻找的东西并有所帮助,我已经使用此模式删除了多余的演员数量,这些演员将所有动作包装在执行不同类型事件的单个演员下。
您可以尝试这样的事情,它涉及通过基本特征自动组合接收功能。先上代码:
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
特征中看到我们设置了一个 Receive
类型的 List
可以通过我们堆叠到具体参与者中的每个特定处理特征来添加它.然后您可以看到每个事件的处理功能的定义,每个事件定义在一个单独的特征中,该特征调用 addHandler
以添加另一部分处理功能。在 preStart
中,对于任何类型的 EventHandlingActor
实现,接收函数将以 receive
为起点(默认为空),然后用 [=21 热交换接收实现=].
现在以几个 impl actor 为例:
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")
}
}
第一个只处理事件,所以它需要做的就是定义它处理我混合在适当特征中的哪些事件。第二个处理一种类型的事件,但也处理其他一些不是事件的消息。 class 覆盖默认的空接收并提供处理非事件消息的功能。
如果我们像这样测试代码:
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")
然后我们会看到类似这样的输出(由于消息的异步处理,顺序发生了变化):
otherHandler handling event1: bar
handler handling event1: foo
handler handling event2: 123
handler handling event3: 123.456
这是我之前问题的延续
我有 10 种类型的事件,这些事件是我需要处理的事件的扩展。
我想在单独的特征中为每个事件实现业务逻辑,因为混合所有 10 个事件处理函数将产生数百(如果不是数千)行代码。
我不想为每个事件创建不同的 Actor 类型。例如:
class Event1Actor extend Actor{
def receive ={
case Event1(e) => //event1 Business Logic
}
}
class Event2Actor extend Actor{
def receive ={
case Event2(e) => //event2 Business Logic
}
}
以及相同的 Event3Actor、Event4Actor 等....
这样的代码在我看来很难看,因为我需要在每个 Actor 内部实现业务逻辑。
实现 10 个不同的特征和 10 个不同的 Actor 类 似乎也是糟糕的设计。
我正在寻找某种基于设计模式的通用解决方案,例如策略模式。
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*/}
希望这就是您正在寻找的东西并有所帮助,我已经使用此模式删除了多余的演员数量,这些演员将所有动作包装在执行不同类型事件的单个演员下。
您可以尝试这样的事情,它涉及通过基本特征自动组合接收功能。先上代码:
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
特征中看到我们设置了一个 Receive
类型的 List
可以通过我们堆叠到具体参与者中的每个特定处理特征来添加它.然后您可以看到每个事件的处理功能的定义,每个事件定义在一个单独的特征中,该特征调用 addHandler
以添加另一部分处理功能。在 preStart
中,对于任何类型的 EventHandlingActor
实现,接收函数将以 receive
为起点(默认为空),然后用 [=21 热交换接收实现=].
现在以几个 impl actor 为例:
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")
}
}
第一个只处理事件,所以它需要做的就是定义它处理我混合在适当特征中的哪些事件。第二个处理一种类型的事件,但也处理其他一些不是事件的消息。 class 覆盖默认的空接收并提供处理非事件消息的功能。
如果我们像这样测试代码:
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")
然后我们会看到类似这样的输出(由于消息的异步处理,顺序发生了变化):
otherHandler handling event1: bar
handler handling event1: foo
handler handling event2: 123
handler handling event3: 123.456