第二十九节 DSL中运用构建者模式

1、看下上节的代码:

fun main(args: Array) {


    val p=person {
        name = "张三"
        age = 10
        address {
            city = "北京市"
            street = "北三环街道"
            number = 100000

        }
    }

    //这儿可以对name单独修改,如果我们不想这么做呢?
    p.name="李四"


}
/**
 * 定义address方法
 */
fun Person.address(block:Address.()->Unit)
{
    this.address=Address().apply(block)
}
/**
 * 首先定义一个方法person,这个返回定义好的Person对象
 */
fun person(block:Person.()->Unit):Person
{
    return Person().apply(block)

}


/**
 * 我们直接定义成data类型,便于打印
 * 城市、街道、街道号
 */
data class Address(var city:String?=null,var street:String?=null,var number:Int?=null)

/**
 * 姓名、年龄、地址
 */
data class Person(var name:String?=null,var age:Int?=null,var address: Address?=null)

问题:
//这儿可以对name单独修改,如果我们不想这么做呢?
p.name="李四"
2、构建者模式介绍
看下android中的一段代码,就使用了构建者模式,什么意思呢?

new Notification.Builder(this)
                .setSmallIcon(R.drawable.ic_launcher)
                .setTicker("您有新短消息,请注意查收!")
                .setContentTitle("Title")
                .setContentText("message")
                .build();

我们自己实现下类似的代码:

public class Notifycation {

    private String title;
    private String content;
    private String time;

    private Notifycation(Build build)
    {
        this.title=build.title;
        this.content=build.content;
        this.time=build.time;
    }

    static class Build
    {
         String title;
         String content;
         String time;

         public Build setTitle(String title)
         {
             this.title=title;
             return this;
         }
         public Build setContent(String content)
         {
             this.content=content;
             return  this;
         }
         public Build setTime(String time)
         {
             this.time=time;
             return this;
         }

         public Notifycation build()
         {
             return new Notifycation(this);
         }
    }
}

现在我们也可以这样写了:

public static void main(String[] args) {

        new Notifycation.Build()
                .setTitle("标题")
                .setContent("内容")
                .setTime("时间")
                .build();

    }

所以构建器模式思想就是先通过一个三方类保存需要的变量 最终拿到所有的变量字段之后 再创建需要的对象Notification
3、我们利用构建者模式解决最开始提出的问题

fun main(args: Array) {


    val p=person {
        name = "张三"
        age = 10
        address {
            city = "北京市"
            street = "北三环街道"
            number = 100000

        }
    }
    //这个代码编译期会报错
//    p.name=""
    println(p)

}
/**
 * 定义address方法
 */
fun PersonBuilder.address(block:Address.()->Unit)
{
    var address=Address()
    block.invoke(address)
    this.address=address
}
/**
 * 首先定义一个方法person,这个返回定义好的Person对象
 */
fun person(block:PersonBuilder.()->Unit):Person
{
    var personBuilder=PersonBuilder()
    block.invoke(personBuilder)
    return Person(personBuilder.name,personBuilder.age,personBuilder.address)
}


/**
 * 我们直接定义成data类型,便于打印
 * 城市、街道、街道号
 */
data class Address(var city:String?=null,var street:String?=null,var number:Int?=null)

/**
 * 姓名、年龄、地址
 */
data class Person(val name:String?,val age:Int?,val address: Address?)


data class PersonBuilder(var name:String?=null,var age:Int?=null,var address: Address?=null)



输出:


image.png

4、同理,可以对Address也运用构建者模式

fun main(args: Array) {


    val p=person {
        name = "张三"
        age = 10
        address {
            city = "北京市"
            street = "北三环街道"
            number = 100000

        }
    }
    //这个代码编译期会报错
//    p.name=""
    println(p)

}
/**
 * 定义address方法
 */
fun PersonBuilder.address(block:AddressBuilder.()->Unit)
{
    var addressBuilder=AddressBuilder()
    block.invoke(addressBuilder)
    this.address=Address(addressBuilder.city,addressBuilder.street,addressBuilder.number)
}
/**
 * 首先定义一个方法person,这个返回定义好的Person对象
 */
fun person(block:PersonBuilder.()->Unit):Person
{
    var personBuilder=PersonBuilder()
    block.invoke(personBuilder)
    return Person(personBuilder.name,personBuilder.age,personBuilder.address)
}


/**
 * 我们直接定义成data类型,便于打印
 * 城市、街道、街道号
 */
data class Address(val city:String?,val street:String?,val number:Int?)

data class AddressBuilder(var city:String?=null,var street:String?=null,var number:Int?=null)

/**
 * 姓名、年龄、地址
 */
data class Person(val name:String?,val age:Int?,val address: Address?)


data class PersonBuilder(var name:String?=null,var age:Int?=null,var address: Address?=null)



输出:


image.png

你可能感兴趣的:(第二十九节 DSL中运用构建者模式)