构造器模式的具体作用和setter的区别
1.构造器模式其实没有什么神秘性,它最终实现的功能和通过先new对象,然后一行一行调用该对象的setter来设置(注意,不是初始化)该对象的属性,最终形成的对象没有区别;
2.那构造器的作用是什么呢?作用如下:
2.1和用setter初始化对象属性最大的区别在于 构造器是要求先给出 该类型所有要初始化字段的 值,通过链式调用设置,全部初始化字段值 给出后,再调用build方法初始化该对象并返回;
所以这里的区别有点像C#里的流,前面设置一堆流处理逻辑,只有最后一步是产生List对象;
即先给出类型所有要初始化字段的所有字段值,然后以这些值来初始化创建该对象(注意,不是先创建,然后set,而是初始化时给定这些初始值);
即没有build之前的字段设置是在对象创建之前的,而setter是值对象创建之后的;
2.2第二个就是可以链式调用初始化;
2.3构造器模式不会暴露类的setter方法,构造器的设置值的方法只在类对象初始化的时候用到,build创建好对象后builder的设置值的方法就没有用了;
所以可以实现类Foo的三个字段都是没有setter的,但是又希望能可选择的初始化(比如只初始化两个字段),如果没有构造器则必须实现很多个构造方法;
因此Foo的构造器一般是在Foo类里面,这样可以在Foo没有暴露setter方法的前提下给Foo字段设值:
class Foo {
private Integer age;
private String name;
private String num;
// 这三个字段只有getter,没有setter,getter代码就不写了知道有就行
public static FooBuilder builder() {
return new FooBuilder();
}
public class static FooBuilder {
// 这里可以用比如Pair<Boolean, Integer> age来更加明确知道age有没有被设置
// 设置了则Boolean为true,否则是false,然后build的时候要判断是true才初始化Foo的age
private Integer age;
private String name;
private String num;
FooBuilder age(Integer age) {
this.age = age;
return this;
}
FooBuilder name(Strng name) {
this.name = name;
return this;
}
FooBuilder num(String num) {
this.num = num;
return this;
}
Foo build() {
Foo foo = new Foo();
// TODO 这里还可以判断this.age是否为空或者默认值,如果是空则不对foo.age设值(看具体Builder策略来实现)
foo.age = this.age;
foo.name = this.name;
foo.num = this.num;
return foo;
}
}
}
通过上面的构造器实现,则可以保留Foo不对外提供setter的权限控制,但是在初始化时又能链式的对所有Foo字段的可选择的初始化,且FooBuilder对象在build后再进行age(..)等设值不会影响已经build出的Foo对象(即Foo对象初始化后就不提供
对外setter;如果用构造方法实现就要很多个构造方法)
而且Builder还能通过多个Builder对象来实现,如必须先填name,再填password,然后其他;可以在builder()方法返回NameStepBuilder(只有name方法,没有build方法因为要求必须name和password都填了才能build),而此接口的name(..)方法返回PasswordStepBuilder(只有password和build方法),而password(..)则返回OtherStepBuilder对象,这里是其他字段的设置方法和build方法,且它包含有NameStepBuilder和PasswordBuilder对象;
还能在build里对整体做合法性校验,比如要求age不能大于多少且name不为多少的这种多个字段的联合校验。
posted on 2023-10-25 12:06 Silentdoer 阅读(34) 评论(0) 编辑 收藏 举报