如何创建具有特征的基于组件的消息处理系统?

时间:2011-03-24 20:53:32

标签: oop scala types

以下是我想要做的简短示例:

abstract class Message()
case class FooMessage() extends Message
case class BarMessage() extends Message
//... other messages ...

trait Component
{
  def handleMessage(msg: Message):Unit
}

trait ComponentType1 extends Component
{
  abstract override def handleMessage(msg: FooMessage) = {
    //handle foo, pass it up the chain
    super.handleMessage(msg)
  }

  abstract override def handleMessage(msg: BarMessage) = {
    //handle bar, pass it up the chain
    super.handleMessage(msg)
  }
}

//handles some other messages, also might handle the same messages as ComponentType1
trait ComponentType2 extends Component { .. }

然后,这些ComponentType 中混合到一个类中,形成一个完全由模块化组件组成的对象。

我有一堆不同的Message和一堆不同的Component

  • 并非所有组件都处理所有消息类型。
  • 多个组件可以处理相同的消息类型。
    • 消息通过组件级联,即使它由另一个组件处理。
  • 组件可以处理多种消息类型。

问题在于,handleMessageComponent中定义为接受Message,当我尝试专门化msg参数时,它不算作覆盖。

我知道一个可能的解决方案是使用大匹配语句声明一个大的handleMessage方法,但是如果可能的话,我想为每条消息定义一个方法。

3 个答案:

答案 0 :(得分:3)

这是基于部分功能的解决方案。向CheatEx提示这个想法。

trait Message   
class FooMessage extends Message 
class BarMessage extends Message 

abstract class Component {
  type CPF = PartialFunction[Message, Unit]

  var pf: CPF  = { case _ => }

  def handleMessage(msg: Message) = pf(msg)
}

trait ComponentType1 extends Component {
  val ct1pf: CPF = {
    case msg: FooMessage => println("foo1")
    case msg: BarMessage => println("bar1")
  }
  pf = ct1pf orElse pf
}

trait ComponentType2 extends Component {
  val parentPf = pf
  val ct2pf: CPF = {
    case msg: 
      BarMessage => println("bar2")
      parentPf(msg)    // cascade 
  }
  pf = ct2pf orElse pf
}

object component1and2 extends ComponentType1 with ComponentType2

component1and2.handleMessage(new FooMessage)
component1and2.handleMessage(new BarMessage)

打印

foo1
bar2
bar1

答案 1 :(得分:1)

trait Message   
class FooMessage extends Message 
class BarMessage extends Message 

trait Component {
  def handleMessage(msg: Message) {}
  def handleMessage(msg: FooMessage) {}
  def handleMessage(msg: BarMessage) {}
}

trait ComponentType1 extends Component {
  override def handleMessage(msg: FooMessage) = println("foo1")
  override def handleMessage(msg: BarMessage) = println("bar1")
}

trait ComponentType2 extends Component {
  override def handleMessage(msg: BarMessage) = println("bar2")
}

object component1and2 extends ComponentType1 with ComponentType2

component1and2.handleMessage(new FooMessage)
component1and2.handleMessage(new BarMessage)

打印

foo1
bar2

如果您在系统中的所有组件的某个位置有一个列表,那么

componentList.foreach(c => c.handleMessage(msg))

对于没有处理msg的组件,它只会在Component中无操作。

答案 2 :(得分:0)

为了完整性:

trait Message   
class FooMessage extends Message 
class BarMessage extends Message 

trait Component {
  def handleMessage(msg: Message) {}
}

trait ComponentType1 extends Component {
  def handleMessage(msg: Message) {
    msg match {
      case m: FooMessage => println("foo1")
      case m: BarMessage => println("bar1")
      case _ => super.handleMessage(msg)
    }
  }
}

trait ComponentType2 extends Component {
  override def handleMessage(msg: Message) {
    msg match {
      case m: BarMessage =>
        println("bar2")
        super.handleMessage(m)    // cascade 
      case _ => super.handleMessage(msg)
    }
  }
}

object component1and2 extends ComponentType1 with ComponentType2

component1and2.handleMessage(new FooMessage)
component1and2.handleMessage(new BarMessage)

打印

foo
bar2
bar1