本文记录如何自定义DSL,帮助你从无脑的硬编码走出来。希望对提高团队代码质量有所帮助。
1. 实现
首先定义bean类,再给bean类添加相应的lambda函数。然后添加单例,我们使用单例来作为所有bean的容器,
并实现你需求的方法。
// DslRule.kt
class Button(){
}
class Text(){
}
class Layout{
fun button(action: Button.() -> Unit){
}
fun text(action: Text.() -> Unit){
}
}
fun layout(action:Layout.() -> Unit){
}
data class TempTime(val temp: Int, val time:Int)
data class Param(val name:String,val resId:Int, val mod: String, val recipe:Int,val tt: TempTime,val shake:Boolean)
class Product(val configMod:String){
lateinit var hashSets:HashSet<Param>
init {
Builder.instance.getMap()[configMod] = this
}
fun init(action:Product.() -> Unit): Product{
action.invoke(this)
return this
}
fun add(vararg params: Param){
hashSets = params.toHashSet()
}
fun printMap(){
hashSets.forEach {
println(it)
}
}
override fun toString(): String {
return "Product(configMod='$configMod')"
}
}
/**
* 1.根据config取出所有预设参数
* 2.根据Mode取出对应的name icon
*
*
*/
class Builder(){
companion object{
val instance: Builder by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED){
Builder()
}
private val map = HashMap<String,Product>()
}
fun getMap() : HashMap<String,Product>{
return map
}
fun getNameByMode(mod: String) : String{
map.forEach {
it.value.hashSets.forEach { p ->
if (p.mod == mod) return p.name
}
}
return ""
}
fun printMap(){
map.forEach {
println(it.value)
}
}
}
fun build(lambda:Builder.() -> Unit) : Builder{
val builder = Builder()
lambda.invoke(builder)
return builder
}
2. 测试
接下来便是测试使用
// DslTest.kt
fun main(){
/**
* 1.{}属于lambda体
* 2.{}里面有button text 需要让它持有this
*/
// infax 表达式必须是成对的
// 模拟compose,,声明式UI
layout {
button {
}
text {
}
}
val builder = build {
Product("DS03").init {
val tempTime = TempTime(12,34)
add(
Param("土豆",12,mod = "M1",24,tempTime,true),
Param("烧烤",12,mod = "M2",24,tempTime,true)
)
}.printMap()
Product("DS04")
.add(
Param("辣椒",12,mod = "M3",24,TempTime(12,34),true),
Param("炒肉",12,mod = "M4",24,TempTime(12,34),true)
)
Product("DS06")
.add(
Param("螺蛳粉",12,mod = "M5",24,TempTime(12,34),true),
Param("番茄",12,mod = "M6",24,TempTime(12,34),true)
)
}
builder.printMap()
println(Builder.instance.getNameByMode("M6"))
}
3. 优点整理
最后重点说一下,自定义Dsl的优点,这些优点主要体现在移动端开发。web后台也有相似优点,因为kt是一种全平台语言。
- 数据添加方便
- resId 和 数据混合使用方便,通常业务最好将resID和业务字段分开管理
- 数据管理统一使用方便,会存在如下情况:
根据Mode转换对应的Name Icon对象、根据config取出所有预设参数或对应模式的预设参数;
可以减少部分字段需要转换后再使用的工作量,如UI展示使用的bean和业务数据使用的bean未封装在一起时会需要转换,
有时仅用到了bean的部分字段会有同学将bean转换成另外一种bean
如果文章还不错,欢迎点赞收藏~打赏~