Java中的builder设计模式

一、为什么要有builder设计模式?

一般情况下,我们初始化对象,是下面这样的:

1、假设我们有一个Phone类,该类有属性(操作系统os、处理器processor、屏幕尺寸screenSize、电池battery和品牌brand):

package Phone;

public class Phone {
    private String os;
    private String processor;
    private double screenSize;
    private int battery;
    private String brand;

    public Phone(String os, String processor, double screenSize, int battery, String brand) {
        this.os = os;
        this.processor = processor;
        this.screenSize = screenSize;
        this.battery = battery;
        this.brand = brand;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "os='" + os + '\'' +
                ", processor='" + processor + '\'' +
                ", screenSize=" + screenSize +
                ", battery=" + battery +
                ", brand='" + brand + '\'' +
                '}';
    }
}

我们为该类创建了Constructor,并重写了toString方法。

此时,我们要在Shop类中实例化Phone对象的方式是这样的:(直接使用构造器初始化)

package Phone;

public class Shop {
    public static void main(String[] args) {
        Phone phone = new Phone("Android","麒麟",1080,9999,"HuaWei");
        System.out.println(phone);
    }
}

输出结果为:

Phone{os='Android', processor='麒麟', screenSize=1080.0, battery=9999, brand='HuaWei'}

Tips:在sout语句里输出实例对象,它会默认调用该对象类的toString方法。(通俗的说就是sout(phone),会默认调用Phone类中的toString方法)


以上这种方式的弊端:

如果我只想定义phone对象的部分参数,例如:我只想买华为(brand)的大屏幕(screenSize)手机,至于处理器(processor)、电池容量(battery)和操作系统(os)我都不懂也不关心。那么我们就要再定义一个只需传入brand和screenSize参数的构造器,就很麻烦。(可能买手机的这个例子并不觉得麻烦,但很麻烦的情况是会出现的)

此时,就可以使用builder模式,来解决上述的弊端。

二、builder模式使用

  1. 首先我们创建一个PhoneBuilder类,该类拥有Phone类的所有属性。
  2. 为PhoneBuilder类中的属性创建setter方法,这些setter方法的返回值类型是PhoneBuilder。
  3. 在PhoneBuilder类中写build()方法,目的是返回Phone类的实例化对象。

PhoneBuilder类的代码如下:

package Phone;

public class PhoneBuilder {
    private String os;
    private String processor;
    private double screenSize;
    private int battery;
    private String brand;

    public PhoneBuilder setOs(String os) {
        this.os = os;
        return this;  //这里的return this,按我的理解就是返回设置了Os属性的PhoneBuilder对象,如果不对,请指正。
    }

    public PhoneBuilder setProcessor(String processor) {
        this.processor = processor;
        return this;
    }

    public PhoneBuilder setScreenSize(double screenSize) {
        this.screenSize = screenSize;
        return this;
    }

    public PhoneBuilder setBattery(int battery) {
        this.battery = battery;
        return this;
    }

    public PhoneBuilder setBrand(String brand) {
        this.brand = brand;
        return this;
    }

    public Phone build(){
        return new Phone(os,processor,screenSize,battery,brand);  //括号里面的参数os,processor,screenSize,battery,brand,其实对应的就是最上面的属性,即把PhoneBuilder的属性当作参数穿给Phone的构造器
    }
}

此时,我们在Shop类中实例化Phone对象,是这样做的:

我们实例化一个PhoneBuilder类,然后调用PhoneBuilder类中的setOs()、setProcessor()、setScreenSize()、setBattery()、setBrand()方法来设置phone对象的参数。最后调用PhoneBuilder类中的build()方法,将我们设置了参数的phone对象返回,以此完成phone对象的初始化。

package Phone;

public class Shop {
    public static void main(String[] args) {
        Phone phone = new PhoneBuilder()
                .setOs("Android")
                .setProcessor("麒麟")
                .setScreenSize(1080)
                .setBattery(9999)
                .setBrand("HuaWei")
                .build();
        System.out.println(phone);
    }
}

输出结果为:

Phone{os='Android', processor='麒麟', screenSize=1080.0, battery=9999, brand='HuaWei'}


这样做的好处在于,假设我只想买华为(brand)的大屏幕(screenSize)手机,至于处理器(processor)、电池容量(battery)和操作系统(os)我都不懂也不关心。那么就可以像下面这样做:(而不用再去写只有brand和screenSize两个参数的构造器)

package Phone;

public class Shop {
    public static void main(String[] args) {
        Phone phone = new PhoneBuilder()
                .setScreenSize(1080)   //个人理解:这里的setScreenSize等方法,其实是在给PhoneBuilder对象设置属性。只不过在最后的build方法里面,将PhoneBuilder对象的这些属性值,当作参数传递给Phone对象的构造器,以此初始化Phone对象。
                .setBrand("HuaWei")
                .build();
        System.out.println(phone);
    }
}

输出结果为:

Phone{os='null', processor='null', screenSize=1080.0, battery=0, brand='HuaWei'}

可以看见,没有设定的参数os、processor和battery,都是等于默认的初始值。

以上就是关于builder设计模式的简单介绍。

猜你喜欢

转载自blog.csdn.net/SakuraMG/article/details/128468938