设计模式之建造者模式

背景:

当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。

 

当一个类的构造函数参数超过4个,而且这些参数有些是可选的时,我们通常有两种办法来构建它的对象。 例如我们现在有如下一个类计算机类Computer,其中cpu与ram是必填参数,而其他3个是可选参数,那么我们如何构造这个类的实例呢,通常有两种常用的方式:

public class Computer {     private String cpu;//必须     private String ram;//必须     private int usbCount;//可选     private String keyboard;//可选     private String display;//可选 }

第一:折叠构造函数模式(telescoping constructor pattern ),这个我们经常用,如下代码所示

public class Computer {      ...     public Computer(String cpu, String ram) {         this(cpu, ram, 0);     }     public Computer(String cpu, String ram, int usbCount) {         this(cpu, ram, usbCount, 罗技键盘);     }     public Computer(String cpu, String ram, int usbCount, String keyboard) {         this(cpu, ram, usbCount, keyboard, 三星显示器);     }     public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {         this.cpu = cpu;         this.ram = ram;         this.usbCount = usbCount;         this.keyboard = keyboard;         this.display = display;     } }

第二种:Javabean 模式,如下所示

public class Computer {         ...      public String getCpu() {         return cpu;     }     public void setCpu(String cpu) {         this.cpu = cpu;     }     public String getRam() {         return ram;     }     public void setRam(String ram) {         this.ram = ram;     }     public int getUsbCount() {         return usbCount;     } ... }

那么这两种方式有什么弊端呢?

第一种主要是使用及阅读不方便。你可以想象一下,当你要调用一个类的构造函数时,你首先要决定使用哪一个,然后里面又是一堆参数,如果这些参数的类型很多又都一样,你还要搞清楚这些参数的含义,很容易就传混了。。。那酸爽谁用谁知道。

第二种方式在构建过程中对象的状态容易发生变化,造成错误。因为那个类中的属性是分步设置的,所以就容易出错。

为了解决这两个痛点,builder模式就横空出世了。

下面代码就是最终的样子

public class Computer {     private final String cpu;//必须     private final String ram;//必须     private final int usbCount;//可选     private final String keyboard;//可选     private final String display;//可选      private Computer(Builder builder){         this.cpu=builder.cpu;         this.ram=builder.ram;         this.usbCount=builder.usbCount;         this.keyboard=builder.keyboard;         this.display=builder.display;     }     public static class Builder{         private String cpu;//必须         private String ram;//必须         private int usbCount;//可选         private String keyboard;//可选         private String display;//可选          public Builder(String cup,String ram){             this.cpu=cup;             this.ram=ram;         }          public Builder setUsbCount(int usbCount) {             this.usbCount = usbCount;             return this;         }         public Builder setKeyboard(String keyboard) {             this.keyboard = keyboard;             return this;         }         public Builder setDisplay(String display) {             this.display = display;             return this;         }                 public Computer build(){             return new Computer(this);         }     }   //省略getter方法 }

如何使用

在客户端使用链式调用,一步一步的把对象构建出来。

Computer computer=new Computer.Builder(因特尔,三星)                 .setDisplay(三星24寸)                 .setKeyboard(罗技)                 .setUsbCount(2)                 .build();