scala-issue为无界类型泛型类创建工厂

cigdeys3  于 2021-07-06  发布在  Java
关注(0)|答案(0)|浏览(171)

我正在尝试编写一些通用代码,可以处理不同类型的输入消息,应用一些工作流逻辑,并为每条消息调用回调。
在下文中, T 以及 S 可以是 Any ; 他们之间可能没有任何共同点

object GenericTest {

  trait DataTransformer[T, S] {
    def transformData(topic: String, message: T) : S
  }

  case class Operation[T, S](transformer: DataTransformer[T, S])

  class WorkflowFlowhandler[T, S] {

    //Common logic that handle bathces for any type of message: T  
    def handleBatch(messages:  List[T], dataTransformers: List[DataTransformer[T, S]]) = {

      val conditionA = true
      val conditionB = true
      //psuedo code
      messages.foreach { message =>

        dataTransformers.foreach{ transformer =>

          //For each message new instance of PartitionerHandler should be created based on some premises
          if(conditionA && conditionB) {
            val ph = PartitionHandler("All") //PartitionHandler[_ <: GenericTest.MessageA, _ <: String]
            ph.process(message, transformer) //type mismatch; found : message.type (with underlying type T) required: _1
          } else {
            val ph = PartitionHandler("A") //PartitionHandler[_ <: GenericTest.MessageA, _ <: String]
            ph.process(message, transformer)
          }
        }
      }
    }
  }

  trait PartitionHandler[T, S] {
    def process(message: T, transformer: DataTransformer[T, S])
  }

  object PartitionHandler {
    //Factory method
//Following returns `PartitionHandler[_ <: GenericTest.MessageA, _ <: String]` which seems to be a problem
    def apply(premise: String ) = premise match {
      case "All" => new AllPartitionHandler
      case "A" => new TopicAPartitionHandler
    }
  }

  class TopicAPartitionHandler extends PartitionHandler[MessageA, String] {

    override def process(message: MessageA, transformer: DataTransformer[MessageA, String]) {

    }

  }

  class AllPartitionHandler[T, S] extends PartitionHandler[T, S] {

    override def process(message: T, transformer: DataTransformer[T, S]) {

    }
  }

  case class MessageA(id: Int, name: String)

  object Execute {

    def init[T, S](messages:  List[T], dataTransformers: List[DataTransformer[T, S]]) {

      val wfhandler = new WorkflowFlowhandler[T, S]
      wfhandler.handleBatch(messages, dataTransformers)

    }
  }

}

我有吗 The Variance Problem 在这里?我需要吗 Marker Traits 让t和s继承?
我想使用通用的handlebatch方法来处理不同类型的消息。问题是工厂 apply 方法 PartitionHandler 不是创建一个我可以作为参数传递给它的示例 process 方法。
编辑
在看了一些在scala和variance示例中为泛型类创建工厂方法的其他示例之后,我想到了下面的示例,这些示例似乎可以工作,但是看起来过于复杂,特别是使用 marker traits . 有没有一种方法可以做到这一点 marker traits ? (我试着用变化、界外球和任何运气来玩)

class WorkflowFlowhandler[T <: MessageMarkerTrait,S <: ResponseMarkerTrait] {

    //Common logic that handle bathces for any type of message: T  
    def handleBatch[T <: MessageMarkerTrait, S <: ResponseMarkerTrait](messages:  List[T], dataTransformers: List[DataTransformer[T, S]]) = {

      val conditionA = true
      val conditionB = true
      //psuedo code
      messages.foreach { message =>

        dataTransformers.foreach{ transformer =>
          import PartitionHandler._
          //For each message new instance of PartitionerHandler should be created based on some premises
          if(conditionA && conditionB) {

            val ph = PartitionHandler[MessageAny, ResponseAny] 
            ph.process(message, transformer) 
          } else {
            val ph = PartitionHandler[MessageA, ResponseA] 
            ph.process(message, transformer)
          }
        }
      }
    }
  }

  trait PartitionHandler[T <: MessageMarkerTrait, S <: ResponseMarkerTrait] {
    def process[T <: MessageMarkerTrait, S <: ResponseMarkerTrait](message: T, transformer: DataTransformer[T, S]) : S
  }

  trait PartitionHandlerFactory[T <: MessageMarkerTrait, S <: ResponseMarkerTrait] {
    def make(): PartitionHandler[T, S]     
  }

  object PartitionHandler {

    def apply[T, S](premise: String ) = premise match {
      case "All" => new AllPartitionHandler()
      case "A" => new TopicAPartitionHandler()
    }

    def apply[T <: MessageMarkerTrait, S <: ResponseMarkerTrait](implicit ev: PartitionHandlerFactory[T, S]) = ev.make()

    implicit val fooImplFactory: PartitionHandlerFactory[MessageAny, ResponseAny] = new PartitionHandlerFactory[MessageAny, ResponseAny] {
      override def make(): PartitionHandler[MessageAny, ResponseAny] = new AllPartitionHandler()
    }

    implicit val anotherFooImplFactory: PartitionHandlerFactory[MessageA, ResponseA] = new PartitionHandlerFactory[MessageA, ResponseA] {
      override def make(): PartitionHandler[MessageA, ResponseA] = new TopicAPartitionHandler()
    }    
  }  

  class MessageA extends MessageMarkerTrait
  class ResponseA extends ResponseMarkerTrait

  class MessageAny extends MessageMarkerTrait
  class ResponseAny extends ResponseMarkerTrait

  class TopicAPartitionHandler[T, S] extends PartitionHandler[MessageA, ResponseA] {

    override def process[T <: MessageMarkerTrait, S <: ResponseMarkerTrait](message: T, transformer: DataTransformer[T, S]) = {
      transformer.transformData("topicA", message)
    }

  }

  class AllPartitionHandler extends PartitionHandler[MessageAny, ResponseAny] {

    override def process[T <: MessageMarkerTrait, S <: ResponseMarkerTrait](message: T, transformer: DataTransformer[T, S]) = {
      transformer.transformData("all", message)
    }
  }

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题