把书读薄 | 《设计模式之美》设计模式与范式(行为型-解释器模式)(下)

简介: 本文对应设计模式与范式:行为型(72),解释器模式 (Interpreter Pattern),用来描述如何构建一个简单的 "语言"解释器。

代码运行输出结果如下


网络异常,图片无法展示
|


使用场景


  • 语言语法较为简单,且对执行效率要求不高时,如正则判断IP是否合法;


  • 问题重复出现,且可用简单语法来进行表达时,如if-else统一解释为条件语句;


  • 当一个语言需要解释执行时,如XML中<>括号标识不同的结点含义;


优点


  • 易于实现语法,一条语法用一个解释器对象解释执行;


  • 易于扩展新语法,只需创建对应解释器,抽象语法树时使用即可;


缺点


  • 可使用场景少,复用性不高,除了发明新的编程语言或对某些新硬件进行解释外,很少用,特定数据结构,扩展性也低;


  • 维护成本高,每种规则至少要定义一个解释类,语法规则越多,类越难管理和维护;


  • 执行效率低,递归调用方法,解释句子语法复杂时,会执行大量循环语句;


0x3、加餐:Kotlin中创建一个自己的DSL示例


顺带提下Kotlin中的DSL,感兴趣的可以看看,用到了下面这些黑魔法:


扩展函数(属性) + lambda表达式 + 中缀表达式 + 运算符重载(invoke)


代码示例如下:


// 饭店
data class Restaurant(var name: String, var score: Int, var price: Int, var address: String)
// 上下文类
data class Eating(
        var kind: String? = "",
        var area: String? = "",
        var restaurantList: List<Restaurant>? = mutableListOf()
) {
    override fun toString() = StringBuilder().apply {
        append("【${this@Eating.area}】的【${this@Eating.kind}】有下述门店:\n\n")
        this@Eating.restaurantList?.forEach { append("${it.name} - ${it.score}分 - ${it.price}元/人 - ${it.address}\n") }
        append("\n")
    }.toString()
}
class RestaurantBuilder {
    var name: String = ""
    var score: Int = 0
    var price: Int = 0
    var address: String = ""
    fun build(): Restaurant = Restaurant(name, score, price, address)
}
// 中间类,用于实现直接DSL方式添加Restaurant的效果
class EatingBuilder {
    var kind: String? = ""
    var area: String? = ""
    var restaurantList = mutableListOf<Restaurant>()
    fun restaurant(block: RestaurantBuilder.() -> Unit) {
        // 此处演示下invoke实现,可以直接restaurantList.add(RestaurantBuilder().apply(block).build())
        val restaurantBuilder = RestaurantBuilder()
        block.invoke(restaurantBuilder)
        restaurantList.add(restaurantBuilder.build())
    }
    fun build(): Eating = Eating(kind, area, restaurantList)
}
// 创建Eating的DSL写法(顶层函数)
fun eating(block: EatingBuilder.() -> Unit): Eating = EatingBuilder().apply(block).build()
// 此处为了演示使用中缀表达式,实际上可以直接赋值
infix fun Eating.area(area: String) {
    this.area = area
}
fun main() {
    val eating = eating {
        kind = "西式快餐"
        restaurant {
            name = "华莱士·全鸡汉堡"
            score = 5
            price = 19
            address = "观澜牛湖店"
        }
        restaurant {
            name = "汉堡王"
            score = 5
            price = 33
            address = "东海店"
        }
        restaurant {
            name = "麦当劳"
            score = 4
            price = 34
            address = "绒花路店"
        }
    }
    eating.area("平湖区")
    println(eating.toString())
}


代码运行输出结果如下


网络异常,图片无法展示
|


以上就是本节课程的全部内容,谢谢~


相关文章
|
3月前
|
设计模式 存储 缓存
Java设计模式 - 解释器模式(24)
Java设计模式 - 解释器模式(24)
|
6月前
|
设计模式 算法
行为型设计模式之模板模式
行为型设计模式之模板模式
|
6月前
|
设计模式 存储
行为型设计模式之观察者模式
行为型设计模式之观察者模式
|
6月前
|
设计模式 算法
行为型设计模式
行为型设计模式
|
7月前
|
设计模式 SQL Java
【设计模式】抖音一面:你不知道解释器模式?
【设计模式】抖音一面:你不知道解释器模式?
62 1
|
7月前
|
设计模式 Go
[设计模式 Go实现] 行为型~状态模式
[设计模式 Go实现] 行为型~状态模式
|
7月前
|
设计模式 Go
[设计模式 Go实现] 行为型~迭代器模式
[设计模式 Go实现] 行为型~迭代器模式
|
7月前
|
设计模式 存储 Go
[设计模式 Go实现] 行为型~备忘录模式
[设计模式 Go实现] 行为型~备忘录模式
|
7月前
|
设计模式 Go
[设计模式 Go实现] 行为型~模板方法模式
[设计模式 Go实现] 行为型~模板方法模式
|
7月前
|
设计模式 Go
[设计模式 Go实现] 行为型~职责链模式
[设计模式 Go实现] 行为型~职责链模式

热门文章

最新文章