Scala中两个结构近似的case class如何无需合并即可优雅重构?
重构方案
以下几种方案都可以在保留Brand和Manufacturer独立case class定义的前提下,消除重复逻辑:
方案1:抽取公共泛型特质封装重复逻辑
适合逻辑集中在伴生对象func方法的场景,原有调用方式完全兼容:
// 定义泛型特质,封装公共构造逻辑 trait AttributeConstructor[T] { // 留给各伴生对象实现的实例构造规则 protected def build(attrValue: String, country: String): T // 公共逻辑仅实现一次 def func(data: (String, String)): T = { // 此处放你原先重复的参数校验、字段预处理等逻辑 val (attr, country) = data build(attr, country) } } case class Brand(brand: String, country: String) object Brand extends AttributeConstructor[Brand] { override protected def build(attrValue: String, country: String): Brand = Brand(attrValue, country) } case class Manufacturer(manufacturer: String, country: String) object Manufacturer extends AttributeConstructor[Manufacturer] { override protected def build(attrValue: String, country: String): Manufacturer = Manufacturer(attrValue, country) }
调用方式和原先完全一致:Brand.func(("华为", "中国"))、Manufacturer.func(("富士康", "中国"))。
方案2:类型类实现(Scala 2/3通用,侵入性更低)
不需要修改原有伴生对象的继承结构,后续新增同类结构的case class扩展成本极低:
// 定义类型类 trait AttributeBuilder[T] { def build(attr: String, country: String): T } // 公共逻辑仅实现一次 def func[T](data: (String, String))(implicit builder: AttributeBuilder[T]): T = { // 此处放你原先重复的公共逻辑 builder.build(data._1, data._2) } // 给两个类注册类型类实例 implicit val brandBuilder: AttributeBuilder[Brand] = Brand(_, _) implicit val manufacturerBuilder: AttributeBuilder[Manufacturer] = Manufacturer(_, _)
调用示例:
val myBrand: Brand = func(("小米", "中国")) val myManufacturer: Manufacturer = func(("比亚迪", "中国"))
方案3:Shapeless自动派生(适合同类case class数量多的场景)
如果后续会新增大量同结构的case class,可以用Shapeless实现自动构造,无需手动给每个类写构造逻辑:
import shapeless._ import shapeless.generic._ def genericFunc[T <: Product](data: (String, String))(implicit gen: Generic.Aux[T, String :: String :: Nil]): T = { // 公共逻辑仅实现一次 gen.from(data._1 :: data._2 :: Nil) }
调用示例:
val brand = genericFunc[Brand](("联想", "中国")) val manufacturer = genericFunc[Manufacturer](("立讯精密", "中国"))
该方案不需要修改原有case class、伴生对象的任何定义,完全无侵入。
内容的提问来源于stack exchange,提问作者TTTT
相关产品推荐
相关产品推荐

