最近在看图解设计模式,其中使用的是java来实现,但是发现其中有的看完后并不知道这个模式是用来干嘛的。一知半解下。通过网上资料辅助理解。就此记录。
后来发现,并不是看不懂,只是书上的例子有些比较老,对比网上的多个例子用的简化方法,书中写的例子都是经典案例,这里记录两种案例。
为什么要用builder模式
对于一个实体类,有两种方法实现构造
方法一、参数不同的构造函数
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, "显示器");
}
}
缺点:构造函数多,当参数多时,含义不明,不易分辨。
new Computer( 1, 2, 3, 4, … )//参数多了就很繁琐
方法二、javabean模式
public class bean{
public String username;
public String password;
XXXset();//实现set和get方法
XXXget();
}
缺点:在使用中途,如果其中的属性值发生变化,要修改的不仅是字段,还有set和get方法,要改的多了,就很烦,还容易漏删、漏改。
builder模式就是为了解决这两个缺点。
什么时候用
当一个类的构造函数的参数多于四个,且有的参数是可选的,考虑使用builder模式
builder模式是什么
明白了为什么用builder和什么时候用后,就开始学习怎么用了。
常用方法(实现后可链式调用)
Computer为主类,其中定义一个静态内部类Builder,定义构造赋值必须的参数,定义set方法赋值可选的参数。
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;//可选的参数,通过set方法赋值
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();//调用结束不要忘了
传统方法
public class Computer {
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private String keyboard;//可选
private String display;//可选
public Computer(String cpu, String ram) {
this.cpu = cpu;
this.ram = ram;
}
public void setUsbCount(int usbCount) {
this.usbCount = usbCount;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public void setDisplay(String display) {
this.display = display;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", usbCount=" + usbCount +
", keyboard='" + keyboard + '\'' +
", display='" + display + '\'' +
'}';
}
}
抽象Builder类
public abstract class ComputerBuilder {
public abstract void setUsbCount();
public abstract void setKeyboard();
public abstract void setDisplay();
public abstract Computer getComputer();
}
具体Builder类,
//第一个具体bulider
public class MacComputerBuilder extends ComputerBuilder {
private Computer computer;
public MacComputerBuilder(String cpu, String ram) {
computer = new Computer(cpu, ram);
}
@Override
public void setUsbCount() {//具体的Builder类中包含其特有的set方法,且提前定义值
computer.setUsbCount(2);
}
@Override
public void setKeyboard() {
computer.setKeyboard("苹果键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("苹果显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
//第二个具体bulider
public class LenovoComputerBuilder extends ComputerBuilder {
private Computer computer;
public LenovoComputerBuilder(String cpu, String ram) {
computer=new Computer(cpu,ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(4);
}
@Override
public void setKeyboard() {
computer.setKeyboard("联想键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("联想显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
Director类
public class ComputerDirector {
public void makeComputer(ComputerBuilder builder){
builder.setUsbCount();
builder.setDisplay();
builder.setKeyboard();
}
}
测试(未完)
public static void main(String[] args) {
ComputerDirector director=new ComputerDirector();//1
ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");
//抽象builder用具体的builder来实例化
director.makeComputer(builder);//通过具体的Builder类来指导Director
Computer macComputer=builder.getComputer();//4
System.out.println("mac computer:"+macComputer.toString());
ComputerBuilder lenovoBuilder=new LenovoComputerBuilder("I7处理器","海力士222");
director.makeComputer(lenovoBuilder);
Computer lenovoComputer=lenovoBuilder.getComputer();
System.out.println("lenovo computer:"+lenovoComputer.toString());
}
题外话:StringBuilder是可以用链式编程的
StringBuilder builder = new StringBuilder().
builder.append("blake").append("bob").append("alice").append("linese").append("eve");
就是利用以下方式实现链式编程的
@Override
public StringBuilder append(String str) {
super.append(str);
return this;//返回当前的对象实例
}