当前位置:首页 » 《随便一记》 » 正文

Kotlin~自定义DSL_Hynson的学习笔记

1 人参与  2021年11月26日 10:03  分类 : 《随便一记》  评论

点击全文阅读


本文记录如何自定义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是一种全平台语言。

  1. 数据添加方便
  2. resId 和 数据混合使用方便,通常业务最好将resID和业务字段分开管理
  3. 数据管理统一使用方便,会存在如下情况:

根据Mode转换对应的Name Icon对象、根据config取出所有预设参数或对应模式的预设参数;
可以减少部分字段需要转换后再使用的工作量,如UI展示使用的bean和业务数据使用的bean未封装在一起时会需要转换,
有时仅用到了bean的部分字段会有同学将bean转换成另外一种bean

如果文章还不错,欢迎点赞收藏~打赏~


点击全文阅读


本文链接:http://zhangshiyu.com/post/31281.html

预设  字段  优点  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1