我对如何改进下面的代码感兴趣。我们的想法是构建一个不可变的可组合构建器。最后,构建器只构建Map [String,Object]。我希望能够定义可以重用的核心构建器组件,并且还允许人们定义自己的其他构建器以扩展主构建器。我能够这样做,但不能没有反思的丑陋使用。代码如下:
object TestPizzaBuilder {
def main(args: Array[String]): Unit = {
val build = new PizzaBuilder()
.withCheese("blue")
.withSauce("tomato")
.build()
println(build)
}
}
object PizzaBuilder {
type BuilderParams = Map[String, Object]
}
class PizzaBuilder(params: BuilderParams = Map.empty) extends BaseBuilder[PizzaBuilder](params: BuilderParams)
with CheeseBuilder[PizzaBuilder]
with SauceBuilder[PizzaBuilder] {
}
abstract class BaseBuilder[A <: BaseBuilder[A]](params: BuilderParams)(implicit tag: ClassTag[A]) {
protected def _copy(tuples: (String, Object)*): A = {
val constr = tag.runtimeClass.getConstructors()(0)
constr.newInstance(params ++ tuples).asInstanceOf[A]
}
def build(): Map[String, Object] = {
params
}
}
trait CheeseBuilder[A <: BaseBuilder[A]] {
this: BaseBuilder[A] =>
def withCheese(cheese: String): A = _copy("cheese" -> cheese)
}
trait SauceBuilder[A <: BaseBuilder[A]] {
this: BaseBuilder[A] =>
def withSauce(sauce: String): A = _copy("sauce" -> sauce)
}
您是否有建议如何在此方案中避免反射,同时保持构建器不可变,并允许组建其他小型构建器的构建器。
答案 0 :(得分:3)
最小的变化是传递构造函数(作为函数)而不是ClassTag
:
abstract class BaseBuilder[A <: BaseBuilder[A]](params: BuilderParams)(constructor: BuilderParams => A) {
protected def _copy(tuples: (String, Object)*): A = constructor(params ++ tuples)
def build(): Map[String, Object] = {
params
}
}
// or class PizzaBuilder(params: BuilderParams = Map.empty) extends BaseBuilder[PizzaBuilder](params)(new PizzaBuilder(_))
case class PizzaBuilder(params: BuilderParams = Map.empty) extends BaseBuilder[PizzaBuilder](params)(PizzaBuilder)
with CheeseBuilder[PizzaBuilder]
with SauceBuilder[PizzaBuilder] {
}