Builder

前言

Builder形式咱们应该不陌生,在咱们的编码生计中,总会碰到它的身影。无论是Android开发中的AlertDialog,仍是网络结构中的OkHttp和Retrofit,亦或是JavaPoet中,都有这哥们的身影。

之所以它这么受欢迎,除了它的上手难度比较低以外,还有一点便是它的的确确的解决了咱们日常开发中的一个难题,创立目标时需求的参数过多

举个小例子

曩昔几年咱们都盛行炒币,导致市面上一卡难求。跟着政府政策的出台,以及虚拟货币的崩盘。显卡不再是有价无市的一种状况。大学刚结业的小龙开了个电脑店,专门给人配电脑。最开端的时分需求比较简单,只给人记载电脑的CPU,GPU,硬盘等相关信息。

传统的创立目标方式

// 电脑类
class Computer {
    private String mBroad;
    private String mCPU;
    private String mGPU;
    public Computer(String broad, String CPU, String GPU) {
        mBroad = broad;
        mCPU = CPU;
        mGPU = GPU;
    }
    @Override
    public String toString() {
        return "Computer{" +
                ", mBroad='" + mBroad + ''' +
                ", mCPU='" + mCPU + ''' +
                ", mGPU='" + mGPU + ''' +
                '}';
    }
}

这个时分创立一个Computer目标是这样的:

Computer computer = new Computer("微星 B550M","INTEL I5","NV 3060TI");

跟着业务量的增大,客户的要求也越来越多。对鼠标,键盘,体系也有了相应的需求。所以Computer类也不得不有了相应的改变。

static class Computer {
    private String mOS;
    private String mBroad;
    private String mKeyBoard;
    private String mMouse;
    private String mCPU;
    private String mGPU;
    public Computer(String OS, String broad, String keyBoard, String mouse, String CPU, String GPU) {
        mOS = OS;
        mBroad = broad;
        mKeyBoard = keyBoard;
        mMouse = mouse;
        mCPU = CPU;
        mGPU = GPU;
    }
    // 就写一个set办法否则文章太长,其他就不写了
    public void setmBroad(String mBroad) {
        this.mBroad = mBroad;
    }
    @Override
    public String toString() {
        return "Computer{" +
                "mOS='" + mOS + ''' +
                ", mBroad='" + mBroad + ''' +
                ", mKeyBoard='" + mKeyBoard + ''' +
                ", mMouse='" + mMouse + ''' +
                ", mCPU='" + mCPU + ''' +
                ", mGPU='" + mGPU + ''' +
                '}';
    }
}

而创立Computer目标的参数也越来越长:

Computer computer = new Computer("MAC OS","微星 B550M","IQUNIX F97"
,"罗技 MX MASTER3","INTEL I5","NV 3060TI");

如果再有新的需求参数,电源,机箱,散热,内存条,硬盘……简直不敢幻想。

目标初始化参数问题

此时咱们面临的是编程中常见的一个问题,目标中需求的参数过多,而都在结构函数传递,则结构函数就会同例子中一样,太长,要是用set办法来传递,则更为恐怖。

这个时分一个形式就应运而生,他便是制作者形式

制作者形式处理方式

/**
 * @author:TianLong
 * @date:2022/10/17 19:58
 * @detail:产品类
 */
class Computer{
    private String mOS;
    private String mBroad;
    private String mKeyBoard;
    private String mMouse;
    private String mCPU;
    private String mGPU;
    private Computer(String OS, String broad, String keyBoard, String mouse, String CPU, String GPU) {
        mOS = OS;
        mBroad = broad;
        mKeyBoard = keyBoard;
        mMouse = mouse;
        mCPU = CPU;
        mGPU = GPU;
    }
    public static ComputerBuilder createBuilder(){
        return new ComputerBuilder();
    }
    @Override
    public String toString() {
        return "Computer{" +
                "mOS='" + mOS + ''' +
                ", mBroad='" + mBroad + ''' +
                ", mKeyBoard='" + mKeyBoard + ''' +
                ", mMouse='" + mMouse + ''' +
                ", mCPU='" + mCPU + ''' +
                ", mGPU='" + mGPU + ''' +
                '}';
    }
    /**
     * @author:TianLong
     * @date:2022/10/17 19:58
     * @detail:产品制作者类
     */
    public static class ComputerBuilder{
        private String mOS = "Windows";
        private String mBroad= "微星 B550M";
        private String mKeyBoard= "无";
        private String mMouse= "无";
        private String mCPU= "Intel I5";
        private String mGPU= "AMD 6600XT";
        public ComputerBuilder setOS(String OS) {
            mOS = OS;
            return this;
        }
        public ComputerBuilder setBroad(String broad) {
            mBroad = broad;
            return this;
        }
        public ComputerBuilder setKeyBoard(String keyBoard) {
            mKeyBoard = keyBoard;
            return this;
        }
        public ComputerBuilder setMouse(String mouse) {
            mMouse = mouse;
            return this;
        }
        public ComputerBuilder setCPU(String CPU) {
            mCPU = CPU;
            return this;
        }
        public ComputerBuilder setGPU(String GPU) {
            mGPU = GPU;
            return this;
        }
        public Computer build(){
            // 能够在build办法中做一些校验等其他作业
            if (mBroad.contains("技嘉")){
                throw new RuntimeException("技嘉辱华,不支持技嘉主板");
            }
            Computer computer = new Computer(mOS,mBroad,mKeyBoard,mMouse,mCPU,mGPU);
            return computer;
        }
    }

老版别和Builder版别创立目标

// 老版别的Computer目标创立
Computer computer = new Computer("MAC OS","微星 B550M","IQUNIX F97"
,"罗技 MX MASTER3","INTEL I5","NV 3060TI");
// Builder版别的Computer目标创立
Computer computer =Computer.createBuilder()
        .setCPU("AMD 5600X")
        .setGPU("NV 3060TI")
        .setMouse("罗技 MX MASTER3")
        .setKeyBoard("IQUNIX F97")
        .build();

两个版别一对比就能表现出来优势。老版别结构函数中的参数太多太长,同一个类型的参数很简单传错位,常常传参数的时分,还要看看第几个参数应该传什么。

Builder形式的目标创立,简单明了,更简单理解,而且流式的调用更加美观,不会犯错。

从代码中能够看到,Computer类的结构函数是私有的,确保了所有目标的创立都有必要从ComputerBuilder这个类来创立。且ComputerBuilder这个类的build办法中,能够进行校验或者其他操作。

同时,Computer这个类中是否存在Set办法,由你的实践应用场景决议,横竖我的使用场景里,没有修改需求。

注意事项

  1. 上述代码为常见写法,并非固定模板。只要能经过Builder类创立目标目标,都能够算是制作者形式
  2. 制作者形式中的目标目标的结构函数有必要是private修饰。否则能够直接创立目标。Builder类就没有意义了
  3. 制作者形式中的目标目标是否需求Set办法,由详细需求决议。一般情况下没有Set办法,能够避免对该目标中的参数进行修改。
  4. Builder中的build办法,能够处理一些逻辑问题,比方校验信息等
  5. 工厂形式注重的是同一类型的目标中经过参数来控制详细创立哪个目标。Builder形式关注的是单一目标中的参数传递