问:建造者模式要解决什么问题。什么时候使用此模式?
比如我们组装一台电脑主机。必要的硬件有CPU 、硬盘、电源、内存、主板。非必要的有独立网卡、散热器。独立显卡等等。
构造函数创建对象
主机
package com.lyy.pattern.builder;
/**
* 电脑主机
* @author ThinkPad
*
*/
public class ComputerMain {
//cpu 必要
private String cpu;
//内存 必要
private String memory;
//电源 必要
private String power;
//硬盘 必要
private String disk;
//主板 必要
private String mainboard;
//独立网卡 非必要
private String independentNetworkCar;
//散热风扇 非必要
private String coolingFan;
/**
* 最基本构造函数
* @param cpu
* @param memory
* @param power
* @param disk
*/
public ComputerMain(String cpu, String memory, String power, String disk, String mainboard) {
this(cpu,memory,power,disk, mainboard, null, null);
}
/**
* 增加一个网卡的构造函数
* @param cpu
* @param memory
* @param power
* @param disk
* @param independentNetworkCar
*/
public ComputerMain(String cpu, String memory, String power, String disk,
String mainboard,String independentNetworkCar) {
this(cpu,memory,power,disk,mainboard,independentNetworkCar, null);
}
/**
* 增加一个网卡和散热器的造函数
* @param cpu
* @param memory
* @param power
* @param disk
* @param independentNetworkCar
* @param coolingFan
*/
public ComputerMain(String cpu, String memory, String power, String disk,
String mainboard, String independentNetworkCar, String coolingFan) {
this.cpu = cpu;
this.memory = memory;
this.power = power;
this.disk = disk;
this.mainboard = mainboard;
this.independentNetworkCar = independentNetworkCar;
this.coolingFan = coolingFan;
}
@Override
public String toString() {
return "ComputerMain [cpu=" + cpu + ", memory=" + memory + ", power=" + power + ", disk=" + disk
+ ", mainboard=" + mainboard + ", independentNetworkCar=" + independentNetworkCar + ", coolingFan="
+ coolingFan + "]";
}
}
main:
package com.lyy.pattern.builder;
public class Main {
public static void main(String[] args) {
//基本电脑主机
ComputerMain baseComputerMain = new ComputerMain("酷睿 i7", "金斯顿 ", "长城", "西部数据" ,"华硕");
System.out.println(baseComputerMain);
//有独立网上的电脑
ComputerMain networkCarComputerMain = new ComputerMain("酷睿 i7", "金斯顿 ", "长城", "西部数据", "华硕", "inter");
System.out.println(networkCarComputerMain);
//有独立网卡和散热风扇的电脑
ComputerMain advaComputerMain = new ComputerMain("酷睿 i7", "金斯顿 ", "长城", "西部数据","华硕" ,"inter","酷冷至尊");
System.out.println(advaComputerMain);
//有散热风扇的电脑
ComputerMain fanComputerMain = new ComputerMain("酷睿 i7", "金斯顿 ", "长城", "西部数据","华硕" ,null,"酷冷至尊");
System.out.println(fanComputerMain);
}
}
上面我们用构造函数来创建对象有几个问题:
1.如果我们非必要的硬件增加独立显卡、固态硬盘、等;那么创建对象很麻烦。
2.如上面:想创建一个带散热器且不带独立网卡的主机时,我们就要在构造函数独立网卡对应位置填null
javaBean方式创建对象
用这种方式可解决上面第2个问题。
//1.先创建一个基本主机
ComputerMain baseComputerMain = new ComputerMain("酷睿 i7", "金斯顿 ", "长城", "西部数据" ,"华硕");
//2.加个风扇
baseComputerMain.setCoolingFan("酷冷至尊");
其他非必要硬件如上也可达到目的。
也有一个问题:
1.阻止了对象被创建完成后的不可变。比如说我们创建完主机,并开机运行,这时肯定是不能再换硬件或增加硬件。(对象创建完不想让改变状态)。但我们可随时调用set方法的。
解决方法:
package com.lyy.pattern.builder;
/**
* 电脑主机
* @author ThinkPad
*
*/
public class ComputerMain2 {
//cpu 必要
private String cpu;
//内存 必要
private String memory;
//电源 必要
private String power;
//硬盘 必要
private String disk;
//主板 必要
private String mainboard;
//独立网卡 非必要
private String independentNetworkCar;
//散热风扇 非必要
private String coolingFan;
/**
* 构造函数
* @param builder
*/
public ComputerMain2(Builder builder) {
this.coolingFan = builder.cpu;
this.cpu = builder.cpu;
this.disk = builder.disk;
this.independentNetworkCar = builder.independentNetworkCar;
this.mainboard = builder.mainboard;
this.memory = builder.mainboard;
this.power = builder.power;
}
/**
* 建造器
* @author ThinkPad
*
*/
public static class Builder{
//cpu 必要
private String cpu;
//内存 必要
private String memory;
//电源 必要
private String power;
//硬盘 必要
private String disk;
//主板 必要
private String mainboard;
//独立网卡 非必要
private String independentNetworkCar;
//散热风扇 非必要
private String coolingFan;
public Builder(String cpu, String memory, String power, String disk, String mainboard) {
this.cpu = cpu;
this.memory = memory;
this.power = power;
this.disk = disk;
this.mainboard = mainboard;
}
public Builder setIndependentNetworkCar(String independentNetworkCar) {
this.independentNetworkCar = independentNetworkCar;
return this;
}
public Builder setCoolingFan(String coolingFan) {
this.coolingFan = coolingFan;
return this;
}
/**
* 创建主机对象
* @return
*/
public ComputerMain2 build() {
return new ComputerMain2(this);
}
}
@Override
public String toString() {
return "ComputerMain [cpu=" + cpu + ", memory=" + memory + ", power=" + power + ", disk=" + disk
+ ", mainboard=" + mainboard + ", independentNetworkCar=" + independentNetworkCar + ", coolingFan="
+ coolingFan + "]";
}
}
ComputerMain2 computerMain2 = new ComputerMain2.Builder("酷睿 i7", "金斯顿 ", "长城", "西部数据" ,"华硕")
.setCoolingFan("酷冷至尊").build();
System.out.println(computerMain2);
现在有这个一个场景:富士康有两个生产线。dell c20 、lenovo P50。既然是生产线那么生产本系列的电脑任何配置都是一样的。所以就没必要每次都set不同的硬件。但是还是以上的需求,开机运行不能修改硬件(创建的对象不能被修改某些参数,不提供set方法)。
上代码 :
package com.lyy.pattern.builder;
/**
* 富士康
* @author ThinkPad
*
*/
public class Fushikang {
public Computer createComputer(Builder builder) {
//builder.setCpu() builder.setMemory()...各各部分的创建这里省略了
return builder.createComputer();
}
}
package com.lyy.pattern.builder;
/**
* 建造器接口
* @author ThinkPad
*
*/
public interface Builder {
public String getCpu();
public String getMemory();
public String getPower();
public String getDisk();
public String getMainboard();
public String getIndependentNetworkCar();
public String getCoolingFan();
public Computer createComputer();
}
package com.lyy.pattern.builder;
public class Computer {
//cpu 必要
private String cpu;
//内存 必要
private String memory;
//电源 必要
private String power;
//硬盘 必要
private String disk;
//主板 必要
private String mainboard;
//独立网卡 非必要
private String independentNetworkCar;
//散热风扇 非必要
private String coolingFan;
/**
* 构造器
* @param builder
*/
public Computer(Builder builder) {
this.coolingFan = builder.getCoolingFan();
this.cpu = builder.getCpu();
this.disk = builder.getDisk();
this.independentNetworkCar = builder.getIndependentNetworkCar();
this.mainboard = builder.getMainboard();
this.memory = builder.getMemory();
this.power = builder.getPower();
}
@Override
public String toString() {
return "Computer [cpu=" + cpu + ", memory=" + memory + ", power=" + power + ", disk=" + disk + ", mainboard="
+ mainboard + ", independentNetworkCar=" + independentNetworkCar + ", coolingFan=" + coolingFan + "]";
}
}
package com.lyy.pattern.builder;
/**
*戴尔c20生产线
* @author ThinkPad
*
*/
public class ProductionLineDellBuilder implements Builder {
public String getCpu() {
// TODO Auto-generated method stub
return "I5-5820";
}
public String getMemory() {
// TODO Auto-generated method stub
return "威刚";
}
public String getPower() {
// TODO Auto-generated method stub
return "戴尔";
}
public String getDisk() {
// TODO Auto-generated method stub
return "戴尔";
}
public String getMainboard() {
// TODO Auto-generated method stub
return "戴尔";
}
public String getIndependentNetworkCar() {
// TODO Auto-generated method stub
return "戴尔";
}
public String getCoolingFan() {
// TODO Auto-generated method stub
return "戴尔";
}
public Computer createComputer() {
return new Computer(this);
}
}
package com.lyy.pattern.builder;
/**
* 联想 P50生产线
* @author ThinkPad
*
*/
public class ProductionLineLenovoBuilder implements Builder {
public String getCpu() {
// TODO Auto-generated method stub
return "AMD X8500";
}
public String getMemory() {
// TODO Auto-generated method stub
return "威刚";
}
public String getPower() {
// TODO Auto-generated method stub
return "联想";
}
public String getDisk() {
// TODO Auto-generated method stub
return "联想";
}
public String getMainboard() {
// TODO Auto-generated method stub
return "联想";
}
public String getIndependentNetworkCar() {
// TODO Auto-generated method stub
return "联想";
}
public String getCoolingFan() {
// TODO Auto-generated method stub
return "联想";
}
public Computer createComputer() {
return new Computer(this);
}
}
main
Fushikang fushikang = new Fushikang();
Computer dellComputer = fushikang.createComputer(new ProductionLineDellBuilder());
Computer lenovoComputer = fushikang.createComputer(new ProductionLineLenovoBuilder());
System.out.println(dellComputer);
System.out.println(lenovoComputer);
打印
Computer [cpu=I5-5820, memory=威刚, power=戴尔, disk=戴尔, mainboard=戴尔, independentNetworkCar=戴尔, coolingFan=戴尔]
Computer [cpu=AMD X8500, memory=威刚, power=联想, disk=联想, mainboard=联想, independentNetworkCar=联想, coolingFan=联想]
总结(个人结论,不一定对!~~):
创建一个多属性或复杂对象、并且创建完的实例某些参数不想被修改(不提供set方法)时可考虑建造者模式。
最后给张类图: