1、定义
DSL(domain specific language),即领域专用语言:专门解决某一特定问题的计算机语言,比如JSON、XML、Anko等
2、外部DSL
- JSON、XML、CSS、SQL、MakeFile等
上面几种语言,它们拥有自己特定的语法结构,并且不需要依赖其他任何通用开发语言,可以单独存在的。我们称为外部DSL。
比如:JSON,它可以单独作为一段单独文本,供给其他语言去使用。
3、内部DSL
- Anko、Kolley、build.gradle等
上面几种,它们也拥有自己特定的语法结构,但是需要依赖Java或者Kotlin语言,它们才能运行的DSL语言,我们称之为内部DSL。
4、DSL优势
- 提高开发效率
就比如我们写一段JSON格式数据文本,如果我们按照JSON语法结构的话,可以很快的书写出来,但是我们使用Java或者Kotlin等通用语言去书写相同的数据文本的话,我们需要定义很多的方法和变量。
- 跨平台
还是用JSON举例,一段JSON格式的数据文本,我们在后台,安卓,IOS等多个平台都能直接使用,但是像Java、Kotlin这种通用语言很难做到这种跨平台性。
5、Anko的简单用例
Anko Layouts 是一套帮助我们更简洁的开发和复用 Android 布局的 DSL ,它的代码风格如下:
相比于笨重的 XML 布局方式,Anko DSL 显然是更先进和更高效的解决方案。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
}
}
6、官方的输出HTML 语言的DSL语法例子
这个例子主要利用Kotlin的Lamda语法,高阶函数来书写了一个可以输出html语句的DSL语言。
import java.io.File
/**
* This is an example of a Type-Safe Groovy-style Builder
*
* Builders are good for declaratively describing data in your code.
* In this example we show how to describe an HTML page in Kotlin.
*
* See this page for details:
* http://kotlinlang.org/docs/reference/type-safe-builders.html
*/
fun main(args: Array<String>) {
val result =
html {
head {
title { +"HTML encoding with Kotlin" }
}
body {
h1 { +"HTML encoding with Kotlin" }
p { +"this format can be used as an alternative markup to HTML" }
// an element with attributes and text content
a(href = "http://jetbrains.com/kotlin") { +"Kotlin" }
// mixed content
p {
+"This is some"
b { +"mixed" }
+"text. For more see the"
a(href = "http://jetbrains.com/kotlin") { +"Kotlin" }
+"project"
}
p { +"some text" }
// content generated from command-line arguments
p {
+"Command line arguments were:"
ul {
for (arg in args)
li { +arg }
}
}
}
}
println(result)
val a=File("a.html")
a.writeText(result.toString())
}
interface Element {
fun render(builder: StringBuilder, indent: String)
}
class TextElement(val text: String) : Element {
override fun render(builder: StringBuilder, indent: String) {
builder.append("$indent$text\n")
}
}
abstract class Tag(val name: String) : Element {
val children = arrayListOf<Element>()
val attributes = hashMapOf<String, String>()
protected fun <T : Element> initTag(tag: T, init: T.() -> Unit): T {
tag.init()
children.add(tag)
return tag
}
override fun render(builder: StringBuilder, indent: String) {
builder.append("$indent<$name${renderAttributes()}>\n")
for (c in children) {
c.render(builder, indent + " ")
}
builder.append("$indent</$name>\n")
}
private fun renderAttributes(): String? {
val builder = StringBuilder()
for (a in attributes.keys) {
builder.append(" $a=\"${attributes[a]}\"")
}
return builder.toString()
}
override fun toString(): String {
val builder = StringBuilder()
render(builder, "")
return builder.toString()
}
}
abstract class TagWithText(name: String) : Tag(name) {
operator fun String.unaryPlus() {
children.add(TextElement(this))
}
}
class HTML() : TagWithText("html") {
fun head(init: Head.() -> Unit) = initTag(Head(), init)
fun body(init: Body.() -> Unit) = initTag(Body(), init)
}
class Head() : TagWithText("head") {
fun title(init: Title.() -> Unit) = initTag(Title(), init)
}
class Title() : TagWithText("title")
abstract class BodyTag(name: String) : TagWithText(name) {
fun b(init: B.() -> Unit) = initTag(B(), init)
fun p(init: P.() -> Unit) = initTag(P(), init)
fun h1(init: H1.() -> Unit) = initTag(H1(), init)
fun ul(init: UL.() -> Unit) = initTag(UL(), init)
fun a(href: String, init: A.() -> Unit) {
val a = initTag(A(), init)
a.href = href
}
}
class Body() : BodyTag("body")
class UL() : BodyTag("ul") {
fun li(init: LI.() -> Unit) = initTag(LI(), init)
}
class B() : BodyTag("b")
class LI() : BodyTag("li")
class P() : BodyTag("p")
class H1() : BodyTag("h1")
class A() : BodyTag("a") {
public var href: String
get() = attributes["href"]!!
set(value) {
attributes["href"] = value
}
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
它的输出结果:
<html>
<head>
<title>
HTML encoding with Kotlin
</title>
</head>
<body>
<h1>
HTML encoding with Kotlin
</h1>
<p>
this format can be used as an alternative markup to HTML
</p>
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
<p>
This is some
<b>
mixed
</b>
text. For more see the
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
project
</p>
<p>
some text
</p>
<p>
Command line arguments were:
<ul>
</ul>
</p>
</body>
</html>
扫描二维码关注公众号,回复:
8860125 查看本文章