用具名可选参数而不是构建者模式
一个经验,就是方法参数不超过五个,否则我们用设计模式解决,我们常用的构建Builder模式。
构建者模式,将一个复杂对象的构建与他的表示,也就是各种属性进行分离,是的同样构造方式,根据参数不同创建不同的表示。
构建者模式可以避免过多的重载函数。
按照Java的Builder构造者模式方式模拟创建一个机器人的模型。
class Robot private constructor(
val code: String?, val battery: String?, val height: Int?, val weight: Int?
){
class Builder(val code:String){
private var battery:String? = null
private var height:Int? = null
private var weight:Int? = null
fun setBattery(battery: String):Builder{
this.battery = battery
return this
}
fun setHeight(height:Int):Builder{
this.height = height
return this
}
fun setWeight(weight:Int):Builder{
this.weight = weight
return this
}
fun build():Robot{
return Robot(code,battery,height,weight)
}
}
}
val robot = Robot.Builder("David")
.setBattery("R8")
.setHeight(180)
.setWeight(140)
.build()
- 如果需求的参数很多,代码依然很长很冗余
- 容易忘记调用build方法
- 创建对象要先创建架构器,增加了开销,在极端情况会存在一定问题
本质上,builder模式模拟了具名可选参数
kotlin具名的可选参数
class Robot(
val code: String,
val battery: String? = null,
val height: Int? = null,
val weight: Int? = null
)
val robot1 = Robot(code = "007")
val robot2 = Robot(code = "007", battery = "R8")
val robot3 = Robot(code = "007", weight = 80, height = 100)
- 代码十分简单,语法简洁
- 每个参数可以是显示的,不需要顺序
- Builder中用到的var,而具名参数用的val更加安全
更好的思路是,如果功能足够简单直接可以用data class直接声明一个数据类,数据类同样支持上面所有特性。
require 约束
在builder我们可以增加约束条件
fun build():Robot{
if(weight!= null && battery == null){
throw IllegalArgumentException("Battery should be determined when setting weight")
}else{
return Robot(code,battery,height,weight)
}
}
Kotlin可以用require达到同样的约束
class Robot(
val code: String,
val battery: String? = null,
val height: Int? = null,
val weight: Int? = null
){
init {
require(weight == null || battery == null){
"Battery should be determined when setting weight"
}
}
}