建造者模式
- 逐步推导建造者模式的由来
- 需求:
- 定义一个电脑类,并且实例化出电脑类的对象,以及给该对象的属性赋值
class Computer {
private String cpu;
private String gpu;
private String memory;
private String hd;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getGpu() {
return gpu;
}
public void setGpu(String gpu) {
this.gpu = gpu;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getHd() {
return hd;
}
public void setHd(String hd) {
this.hd = hd;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", memory='" + memory + '\'' +
", hd='" + hd + '\'' +
'}';
}
}
public class AppTest {
public static void main(String[] args) {
Computer c = new Computer();
c.setCpu("i7 7500u");
c.setGpu("gt940mx");
c.setMemory("16g");
c.setHd("1T机械");
System.out.println(c);
}
}
- 这样做的缺点:
- 客户端程序猿在实例化好产品的对象之后,必须为该对象的每一个属性赋值,这样对客户端程序猿来说,太麻烦了!
- 违反了迪米特法则(最少知道原则), 客户端程序猿知道得太多了
- 这相当于你去配置电脑,商家把零件全给你,你自己组装电脑!
- 针对上面两个问题,修改代码如下:
- 作者,专门创建一个"ComputerBuilder" 类,这个类专门封装组装电脑的过程
class Computer {
private String cpu;
private String gpu;
private String memory;
private String hd;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getGpu() {
return gpu;
}
public void setGpu(String gpu) {
this.gpu = gpu;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getHd() {
return hd;
}
public void setHd(String hd) {
this.hd = hd;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", memory='" + memory + '\'' +
", hd='" + hd + '\'' +
'}';
}
}
class ComputerBuilder {
private Computer computer = new Computer();
public Computer build() {
computer.setCpu("i7 8750HK");
computer.setGpu("rtx2080Ti");
computer.setMemory("32g");
computer.setHd("500g固态+2T机械");
return computer;
}
}
public class AppTest {
public static void main(String[] args) {
ComputerBuilder cb = new ComputerBuilder();
Computer c = cb.build();
System.out.println(c);
Computer c2 = cb.build();
System.out.println(c2);
Computer c3 = cb.build();
System.out.println(c3);
}
}
- 目前的这种写法还不是建造模式
- 目前的优点:
- 客户端程序猿需要一个产品时,直接向建造者要即可,建造者封装了创建电脑的"复杂"过程
- 目前的缺点:
- 封装得太狠了!无论客户得需求什么,都是采用最高配置,这相当于你去配电脑,无论是什么需求,商家都会给你配最贵的电脑!
- 针对封装得太狠了的问题,修改代码如下:
- 针对于不同需求,我们需要创建不同的建造者,来分别生产不同
class Computer {
private String cpu;
private String gpu;
private String memory;
private String hd;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getGpu() {
return gpu;
}
public void setGpu(String gpu) {
this.gpu = gpu;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getHd() {
return hd;
}
public void setHd(String hd) {
this.hd = hd;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", memory='" + memory + '\'' +
", hd='" + hd + '\'' +
'}';
}
}
class AdvancedComputerBuilder {
private Computer computer = new Computer();
public Computer build() {
computer.setCpu("i7 8750HK");
computer.setGpu("rtx2080Ti");
computer.setMemory("32g");
computer.setHd("500g固态+2T机械");
return computer;
}
}
class MiddleComputerBuilder {
private Computer computer = new Computer();
public Computer build() {
computer.setCpu("i7 7700hq");
computer.setGpu("gtx1060");
computer.setMemory("16g");
computer.setHd("250g固态+1T机械");
return computer;
}
}
class LowComputerBuilder {
private Computer computer = new Computer();
public Computer build() {
computer.setCpu("i7 7500u");
computer.setGpu("gtx940mx");
computer.setMemory("8g");
computer.setHd("1T机械");
return computer;
}
}
public class AppTest {
public static void main(String[] args) {
AdvancedComputerBuilder adc = new AdvancedComputerBuilder();
MiddleComputerBuilder mcb = new MiddleComputerBuilder();
LowComputerBuilder lcb = new LowComputerBuilder();
Computer c = adc.build();
System.out.println(c);
Computer c2 = mcb.build();
System.out.println(c2);
Computer c3 = mcb.build();
System.out.println(c3);
}
}
- 这任然不是建造者模式:
- 优点:
- 可以根据客户端的不同需求, 使用不同的建造者来生产产品
- 缺点:
- 我们发现,多个不同的建造者中的代码,在重复!既然代码中出现了重复的代码,那就有了"坏味道"!
- 建造的过程不稳定! 如果在某个建造者创建产品的过程中,漏调了某一步,编译器也不会报错!
(相当于,KFC的某一家分店,你制作汉堡包的流程突然少了某一步骤,出现的汉堡包味道就变了,因为没有标准!)
- 针对以上两个问题,修改代码如下:
- 创建一个建造者接口,把制作产品的具体步骤,稳定下来!
class Computer {
private String cpu;
private String gpu;
private String memory;
private String hd;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getGpu() {
return gpu;
}
public void setGpu(String gpu) {
this.gpu = gpu;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getHd() {
return hd;
}
public void setHd(String hd) {
this.hd = hd;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", memory='" + memory + '\'' +
", hd='" + hd + '\'' +
'}';
}
}
interface ComputerBuilder {
public void setCpu();
public void setGpu();
public void setMemory();
public void setHd();
public Computer build();
}
class AdvancedComputerBuilder implements ComputerBuilder{
private Computer computer = new Computer();
@Override
public void setCpu() {
computer.setCpu("i7 8750HK");
}
@Override
public void setGpu() {
computer.setGpu("rtx2080Ti");
}
@Override
public void setMemory() {
computer.setMemory("32g");
}
@Override
public void setHd() {
computer.setHd("500g固态+2T机械");
}
@Override
public Computer build() {
return computer;
}
}
class MiddleComputerBuilder implements ComputerBuilder{
private Computer computer = new Computer();
@Override
public void setCpu() {
computer.setCpu("i7 7700hq");
}
@Override
public void setGpu() {
computer.setGpu("gtx1060");
}
@Override
public void setMemory() {
computer.setMemory("16g");
}
@Override
public void setHd() {
computer.setHd("250g固态+1T机械");
}
@Override
public Computer build() {
return computer;
}
}
class LowComputerBuilder implements ComputerBuilder{
private Computer computer = new Computer();
@Override
public void setCpu() {
computer.setCpu("i7 7500u");
}
@Override
public void setGpu() {
computer.setGpu("gtx940mx");
}
@Override
public void setMemory() {
computer.setMemory("8g");
}
@Override
public void setHd() {
computer.setHd("1T机械");
}
@Override
public Computer build() {
return computer;
}
}
AdvancedComputerBuilder acb = new AdvancedComputerBuilder();
acb.setCpu();
acb.setGpu();
acb.setMemory();
acb.setHd();
Computer c = acb.build();
System.out.println(c);
MiddleComputerBuilder mcb = new MiddleComputerBuilder();
mcb.setCpu();
mcb.setGpu();
mcb.setMemory();
mcb.setHd();
Computer c2 = mcb.build();
System.out.println(c2);
LowComputerBuilder lcb = new LowComputerBuilder();
lcb.setCpu();
lcb.setGpu();
lcb.setMemory();
lcb.setHd();
Computer c3 = lcb.build();
System.out.println(c3);
- 这还不是建造者模式
- 优点:
- 建造者类中的建造过程是稳定的,不会漏掉某一步!!这样当客户端想扩展建造者时,也不会漏掉某一步
- 缺点:
- 代码任然有重复
- 客户端现在又变成了客户端自己配置电脑,又违反了迪米特法则
(这相当于,去电脑城配电脑,虽然不用你亲自组装电脑,但是你必须"指挥"装机老板,该装什么…该装什么…)
- 针对代码重复,和违反迪米特法则,修改代码如下:
- 建造者模式: 终于进化出来了
class Computer {
private String cpu;
private String gpu;
private String memory;
private String hd;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getGpu() {
return gpu;
}
public void setGpu(String gpu) {
this.gpu = gpu;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getHd() {
return hd;
}
public void setHd(String hd) {
this.hd = hd;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", memory='" + memory + '\'' +
", hd='" + hd + '\'' +
'}';
}
}
interface ComputerBuilder {
public void setCpu();
public void setGpu();
public void setMemory();
public void setHd();
public Computer build();
}
class AdvancedComputerBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public void setCpu() {
computer.setCpu("i7 8750HK");
}
@Override
public void setGpu() {
computer.setGpu("rtx2080Ti");
}
@Override
public void setMemory() {
computer.setMemory("32g");
}
@Override
public void setHd() {
computer.setHd("500g固态+2T机械");
}
@Override
public Computer build() {
return computer;
}
}
class MiddleComputerBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public void setCpu() {
computer.setCpu("i7 7700hq");
}
@Override
public void setGpu() {
computer.setGpu("gtx1060");
}
@Override
public void setMemory() {
computer.setMemory("16g");
}
@Override
public void setHd() {
computer.setHd("250g固态+1T机械");
}
@Override
public Computer build() {
return computer;
}
}
class LowComputerBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public void setCpu() {
computer.setCpu("i7 7500u");
}
@Override
public void setGpu() {
computer.setGpu("gtx940mx");
}
@Override
public void setMemory() {
computer.setMemory("8g");
}
@Override
public void setHd() {
computer.setHd("1T机械");
}
@Override
public Computer build() {
return computer;
}
}
class Director {
public Computer build(ComputerBuilder cb) {
cb.setCpu();
cb.setGpu();
cb.setMemory();
cb.setHd();
return cb.build();
}
}
public class AppTest {
public static void main(String[] args) {
AdvancedComputerBuilder acb = new AdvancedComputerBuilder();
MiddleComputerBuilder mcb = new MiddleComputerBuilder();
LowComputerBuilder lcb = new LowComputerBuilder();
Director director = new Director();
Computer c = director.build(acb);
System.out.println(c);
Computer c2 = director.build(mcb);
System.out.println(c2);
Computer c3 = director.build(lcb);
System.out.println(c3);
MiddleHighComputerBuilder mhcb = new MiddleHighComputerBuilder();
Computer c4 = director.build(mhcb);
System.out.println(c4);
}
}
- 这就是建造者模式
- 即
- 一个稳点建造过程的接口
- 建造者实现建造过程的接口
- 创建一个指挥者,把过程交给指挥者就行了
- 优点:
- 创建对象的工厂是稳定不变的(因为有ComputerBuilder接口来稳定过程)
- 创建对象的过程只写了一次,没有重复代码(指挥者完成)
- 当需要扩展指挥者的时候,不用修改之前的代码,这符合开闭原则
建造者与工厂模式的区别:
- 工厂模式:
- 工厂模式只需要一个简单的new,new出产品即可.
- 建造者模式:
- 建造者更注重在new出产品之后的,为产品属性赋值的过程!