Silentdoer

导航

构造器模式的具体作用和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  阅读(23)  评论(0编辑  收藏  举报