Java设计模式(4)——建造者(Builder)模式

在设计模式系列的前几篇文章里,记录过的工厂模式、单例模式都是为了创建对象而出现的,建造者模式也不例外。

建造者模式的适用场景

有的时候我们编写的类构造器有较多(超过4个)参数,有些参数是必须的,有些参数是可选的。针对这种情况,往往会编写多个构造器,比如:

class Person{
    String name;  // 必须
    int id;   // 必须
    int gender;
    int phoneNumber;
    String address;
    
    public Person(String name, int id, int gender, int phoneNumber, String address){
        this.name = name;
        this.id = id;
        this.gender = gender;
        this.phoneNumber = phoneNumber;
        this.address = address;
    }
    
    public Person(String name, int id, int phoneNumber){
        this.name = name;
        this.id = id;
        this.phoneNumber = phoneNumber;
    }
    
    public Person(String name, int id, int gender, String address){
        this.name = name;
        this.id = id;
        this.gender = gender;
        this.address = address;
    }
}

在C++中,通过设置参数默认值,也可以实现一个构造方法实现多种构造方式。但是Java只能通过重载构造函数来实现。这样做的缺点就是可读性不高,看代码的时候还得仔细判断每个参数对应的是哪个形参,尤其当几个参数数据类型一样,更难判断。Builder设计模式解决了这样的问题。解决方法就是在类里新增一个Builder静态内部类:

class Person{
    private String name;  // 必须
    private int id;   // 必须
    private int gender;
    private int phoneNumber;
    private String address;

    private Person(Builder builder){
        this.name = builder.name;
        this.id = builder.id;
        this.gender = builder.gender;
        this.phoneNumber = builder.phoneNumber;
        this.address = builder.address;
    }

    
    public static class Builder{
        private String name;  // 必须
        private int id;   // 必须
        private int gender;
        private int phoneNumber;
        private String address;

        public Builder(String name, int id){
            this.name = name;
            this.id = id;
        }

        public Builder setGender(int gender){
            this.gender = gender;
            return this;
        }

        public Builder setPhoneNumber(int phoneNumber){
            this.phoneNumber = phoneNumber;
            return this;
        }

        public Builder setAddress(String address){
            this.address = address;
            return this;
        }

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


public class BuilderPattern {
    public static void main(String[] args) {
        Person p = new Person.Builder("mike",123).setAddress("seu street").build();
    }
}

我试了一下,如果不用静态内部类也是可以实现类似的链式调用方法构建对象的:

class Person{
    private String name;  // 必须
    private int id;   // 必须
    private int gender=0;
    private int phoneNumber;
    private String address;

    public Person(String name, int id){
        this.name = name;
        this.id = id;
    }

    public Person setPhoneNumber(int phoneNumber) {
        this.phoneNumber = phoneNumber;
        return this;
    }

    public Person setAddress(String address) {
        this.address = address;
        return this;
    }
}

public class BuilderPattern {
    public static void main(String[] args) {
        Person p = new Person("mike",13).setPhoneNumber(110).setAddress("seu road");
    }
}

但是这样的话,在new Person(“mike”,13)这一步已经可以作为完整的对象构建过程了,已经构建出了一个Person对象,整个语句跟set之后再build相比,更像是把多个语句连续执行,而不是一个独立的创建过程;此外,对于对象的构建这个功能,需要单独创建一个类来执行,更加符合单一职责原则。而且,为了实现这样的链式调用,set方法需要返回Person实例对象;但一般来说,set方法我们会设置他的返回值为空,或者设置一个true/false、状态码来表明是否设置成功,而不是返回一个修改过后的实例对象;因此这些功能还是交给另一个类去做比较好。

你可能感兴趣的:(设计模式)