例1:
package com.woniuxy.k_builder.a; // 需求:用户买电脑. class Computer { private String cpu; private String memery; private String harddisk; private String gpu; public void setCpu(String cpu) { this.cpu = cpu; } public void setMemery(String memery) { this.memery = memery; } public void setHarddisk(String harddisk) { this.harddisk = harddisk; } public void setGpu(String gpu) { this.gpu = gpu; } @Override public String toString() { return "Computer [cpu=" + cpu + ", memery=" + memery + ", harddisk=" + harddisk + ", gpu=" + gpu + "]"; } } public class Test { public static void main(String[] args) { Computer c = new Computer(); c.setCpu("i7 7700hq"); c.setMemery("16"); c.setHarddisk("1T"); c.setGpu("Rtx2080ti"); System.out.println(c); } } // 缺点: // 1. 当一个对象的组成过程特别繁琐,特别麻烦的时候,就不应该让客户端自己来完成。(相当于你去配电脑,卖家把所有组件都给你摆出来,让你自己亲自动手组装)。 // 2. 这样客户端可能会不按正确步骤组装对象,或缺少了某一个组件。 // 3. 这样违反了迪米特法则 // 对比,工厂模式,都是只负责把对象直接实例化出来,不管对象的状态。 建造者特强侧重于把对象new出来以后,给对象的属性赋值!
例2
package com.woniuxy.k_builder.b; // 针对于a包的缺点,重构代码如下: // 1. 作者额外添加一个功能:直接封装装配电脑的工作。 class Computer { private String cpu; private String memery; private String harddisk; private String gpu; public void setCpu(String cpu) { this.cpu = cpu; } public void setMemery(String memery) { this.memery = memery; } public void setHarddisk(String harddisk) { this.harddisk = harddisk; } public void setGpu(String gpu) { this.gpu = gpu; } @Override public String toString() { return "Computer [cpu=" + cpu + ", memery=" + memery + ", harddisk=" + harddisk + ", gpu=" + gpu + "]"; } } class ComputerBuilder { private Computer c = new Computer(); public Computer build() { c.setCpu("i7 7700hq"); c.setMemery("16"); c.setHarddisk("1T"); c.setGpu("Rtx2080ti"); return c; } } // ================================================================== public class Test { public static void main(String[] args) { ComputerBuilder cb = new ComputerBuilder(); // 学习 (cpu好 + 内存 ) Computer c = cb.build(); System.out.println(c); // 玩游戏 Computer c2 = cb.build(); System.out.println(c2); // 娱乐、办公 Computer c3 = cb.build(); System.out.println(c3); } } // 缺点: // 1. 封装地太狠! 无论客户端是什么需求,客户端没办法选择配置! 都是由服务器端定死的配置!! // 应该根据不同需求,配置出不同的 低端、中端、高端电脑.
例3
package com.woniuxy.k_builder.c; // 针对于b包的缺点,重构代码如下: // 1. 针对于不同需求,有不同的建造者。 // 2. 客户端仍然不知道建造电脑的过程。 class Computer { private String cpu; private String memery; private String harddisk; private String gpu; public void setCpu(String cpu) { this.cpu = cpu; } public void setMemery(String memery) { this.memery = memery; } public void setHarddisk(String harddisk) { this.harddisk = harddisk; } public void setGpu(String gpu) { this.gpu = gpu; } @Override public String toString() { return "Computer [cpu=" + cpu + ", memery=" + memery + ", harddisk=" + harddisk + ", gpu=" + gpu + "]"; } } class AdvancedComputerBuilder { private Computer c = new Computer(); public Computer build() { c.setCpu("i9 8700hk"); c.setMemery("64"); c.setHarddisk("2T+512固态硬盘"); c.setGpu("双卡交火 Rtx2080ti"); return c; } } class MiddleComputerBuilder { private Computer c = new Computer(); public Computer build() { c.setCpu("i7 7700hq"); c.setMemery("16"); c.setHarddisk("1T+256固态"); c.setGpu("GTX1070"); return c; } } class LowComputerBuilder { private Computer c = new Computer(); public Computer build() { c.setCpu("i5 3320m"); c.setMemery("8"); c.setHarddisk("500g"); c.setGpu("集成显卡"); return c; } } // ================================================================== public class Test { public static void main(String[] args) { AdvancedComputerBuilder acb = new AdvancedComputerBuilder(); MiddleComputerBuilder mcb = new MiddleComputerBuilder(); LowComputerBuilder lcb = new LowComputerBuilder(); // 学习 Computer c = mcb.build(); System.out.println(c); // 办公、娱乐 Computer c2 = lcb.build(); System.out.println(c2); // 游戏 Computer c3 = acb.build(); System.out.println(c3); } } // 缺点: // 1. 无论是高 中 低哪一种配置的电脑,配置的过程都是一样的,只不过细节不一样。 既然有重复,那就有了坏味道。 // 2. 这些重复的安装步骤,不稳定,万一哪一个建造者中漏了某一个步骤,编译期也不会报错!
例4
package com.woniuxy.k_builder.d; // 针对于c包的缺点,重构代码如下: // 1. 稳定住,建造电脑的过程, 定义一个建造者接口 // 2. 让所有具体建造者实现这个接口,那么所有具体建造者,就必须实现这个接口中的所有方法,就不会遗漏某一个步骤。 interface ComputerBuilder { void setCpu(); void setMemery(); void setHarddisk(); void setGpu(); Computer build(); } class Computer { private String cpu; private String memery; private String harddisk; private String gpu; public void setCpu(String cpu) { this.cpu = cpu; } public void setMemery(String memery) { this.memery = memery; } public void setHarddisk(String harddisk) { this.harddisk = harddisk; } public void setGpu(String gpu) { this.gpu = gpu; } @Override public String toString() { return "Computer [cpu=" + cpu + ", memery=" + memery + ", harddisk=" + harddisk + ", gpu=" + gpu + "]"; } } class AdvancedComputerBuilder implements ComputerBuilder{ private Computer c = new Computer(); @Override public void setCpu() { c.setCpu("i9 8700hk"); } @Override public void setMemery() { c.setMemery("64g"); } @Override public void setHarddisk() { c.setHarddisk("2T + 515固态"); } @Override public void setGpu() { c.setGpu("rtx2080ti"); } @Override public Computer build() { return c; } } class MiddleComputerBuilder implements ComputerBuilder{ private Computer c = new Computer(); @Override public void setCpu() { c.setCpu("i7 7700hq"); } @Override public void setMemery() { c.setMemery("16g"); } @Override public void setHarddisk() { c.setHarddisk("1T + 256固态"); } @Override public void setGpu() { c.setGpu("gtx1070"); } @Override public Computer build() { return c; } } class LowComputerBuilder implements ComputerBuilder{ private Computer c = new Computer(); @Override public void setCpu() { c.setCpu("i5 3320m"); } @Override public void setMemery() { c.setMemery("8"); } @Override public void setHarddisk() { c.setHarddisk("500g"); } @Override public void setGpu() { c.setGpu("集成显卡"); } @Override public Computer build() { return c; } } // ================================================================== public class Test { public static void main(String[] args) { AdvancedComputerBuilder acb = new AdvancedComputerBuilder(); acb.setCpu(); acb.setHarddisk(); acb.setMemery(); acb.setGpu(); Computer c = acb.build(); System.out.println(c); MiddleComputerBuilder mcb = new MiddleComputerBuilder(); mcb.setCpu(); mcb.setHarddisk(); mcb.setMemery(); mcb.setGpu(); Computer c2 = mcb.build(); System.out.println(c2); } } // 缺点: // 1. 客户端又必须知道建造的过程了, (相当于你去配一台电脑,虽然不是自己亲自组装电脑,但是你要只会那个“小伙”,该装...该装...该装...)
例5:
package com.woniuxy.k_builder.e; // 针对于d包的缺点,重构代码如下: // 1. 创建一个指挥者(Director),接受不同的建造者,完成建造过程 interface ComputerBuilder { void setCpu(); void setMemery(); void setHarddisk(); void setGpu(); Computer build(); } class Computer { private String cpu; private String memery; private String harddisk; private String gpu; public void setCpu(String cpu) { this.cpu = cpu; } public void setMemery(String memery) { this.memery = memery; } public void setHarddisk(String harddisk) { this.harddisk = harddisk; } public void setGpu(String gpu) { this.gpu = gpu; } @Override public String toString() { return "Computer [cpu=" + cpu + ", memery=" + memery + ", harddisk=" + harddisk + ", gpu=" + gpu + "]"; } } class AdvancedComputerBuilder implements ComputerBuilder{ private Computer c = new Computer(); @Override public void setCpu() { c.setCpu("i9 8700hk"); } @Override public void setMemery() { c.setMemery("64g"); } @Override public void setHarddisk() { c.setHarddisk("2T + 515固态"); } @Override public void setGpu() { c.setGpu("rtx2080ti"); } @Override public Computer build() { return c; } } class MiddleComputerBuilder implements ComputerBuilder{ private Computer c = new Computer(); @Override public void setCpu() { c.setCpu("i7 7700hq"); } @Override public void setMemery() { c.setMemery("16g"); } @Override public void setHarddisk() { c.setHarddisk("1T + 256固态"); } @Override public void setGpu() { c.setGpu("gtx1070"); } @Override public Computer build() { return c; } } class LowComputerBuilder implements ComputerBuilder{ private Computer c = new Computer(); @Override public void setCpu() { c.setCpu("i5 3320m"); } @Override public void setMemery() { c.setMemery("8"); } @Override public void setHarddisk() { c.setHarddisk("500g"); } @Override public void setGpu() { c.setGpu("集成显卡"); } @Override public Computer build() { return c; } } class Director { public Computer build(ComputerBuilder cb) { cb.setCpu(); cb.setHarddisk(); cb.setMemery(); cb.setGpu(); return cb.build(); } } // ================================================================== public class Test { public static void main(String[] args) { AdvancedComputerBuilder acb = new AdvancedComputerBuilder(); MiddleComputerBuilder mcb = new MiddleComputerBuilder(); Director director = new Director(); Computer c = director.build(mcb); System.out.println(c); } } // 至此,建造者设计模式的第一种形态,推演完毕! // 该形态的缺点是,客户端无法灵活控制组件的细节,比如,客户端无法直接指定cpu或者硬盘的型号。 // 所以才有了建造者模式的第二种形态,而第二种形态又不仅仅是解决以上提到的问题的。
例6:
package com.woniuxy.k_builder.f; import com.woniuxy.k_builder.f.Computer.ComputerBuilder; // 当一个类的属性特别多的时候,构造器的参数也就特别多,尤其是构造器的多个参数类型还都一样。 // 那么客户端代码就很容易出错。 class Computer { private String cpu; private String harddisk; private String memery; private String gpu; private String power; private String motherboard; // 主板 private String cdrom; private String fan; private String netcard; // public Computer(String cpu, String harddisk, String memery, String gpu, String power, String motherboard, // String cdrom, String fan, String netcard) { // super(); // this.cpu = cpu; // this.harddisk = harddisk; // this.memery = memery; // this.gpu = gpu; // this.power = power; // this.motherboard = motherboard; // this.cdrom = cdrom; // this.fan = fan; // this.netcard = netcard; // } public Computer() { } private Computer(ComputerBuilder cb) { this.cpu = cb.cpu; this.harddisk = cb.harddisk; this.memery = cb.memery; this.gpu = cb.gpu; this.power = cb.power; this.netcard = cb.netcard; this.motherboard = cb.motherboard; this.fan = cb.fan; this.cdrom = cb.cdrom; } // 以上的构造器,使用起来确实很麻烦! 也许有小伙伴会这样向,我们可以对构造器进行重载,把参数减少, 事实证明,这也很2.... // 最好的解决方法是使用建造这设计模式的第二种形态 // 1. 建造者必须是产品的一个静态内部类 // 2. 建造者的属性完全与产品的所有属性一致 // 3. 为建造者的每一个属性都添加一个setter方法,且该setter方法必须返回建造者对象本身 // (以前的javabean的setter方法,返回值是void) public static class ComputerBuilder { private String cpu; private String harddisk; private String memery; private String gpu; private String power; private String motherboard; // 主板 private String cdrom; private String fan; private String netcard; public ComputerBuilder setCpu(String cpu) { this.cpu = cpu; return this; } public ComputerBuilder setHarddisk(String harddisk) { this.harddisk = harddisk; return this; } public ComputerBuilder setMemery(String memery) { this.memery = memery; return this; } public ComputerBuilder setGpu(String gpu) { this.gpu = gpu; return this; } public ComputerBuilder setPower(String power) { this.power = power; return this; } public ComputerBuilder setMotherboard(String motherboard) { this.motherboard = motherboard; return this; } public ComputerBuilder setCdrom(String cdrom) { this.cdrom = cdrom; return this; } public ComputerBuilder setFan(String fan) { this.fan = fan; return this; } public ComputerBuilder setNetcard(String netcard) { this.netcard = netcard; return this; } public Computer build() { System.out.println("组装" + cpu + "," + gpu + "," + memery); return new Computer(this); } } @Override public String toString() { return "Computer [cpu=" + cpu + ", harddisk=" + harddisk + ", memery=" + memery + ", gpu=" + gpu + ", power=" + power + ", motherboard=" + motherboard + ", cdrom=" + cdrom + ", fan=" + fan + ", netcard=" + netcard + "]"; } public Computer setCpu(String cpu) { this.cpu = cpu; return this; } public void setHarddisk(String harddisk) { this.harddisk = harddisk; } public void setMemery(String memery) { this.memery = memery; } public void setGpu(String gpu) { this.gpu = gpu; } public void setPower(String power) { this.power = power; } public void setMotherboard(String motherboard) { this.motherboard = motherboard; } public void setCdrom(String cdrom) { this.cdrom = cdrom; } public void setFan(String fan) { this.fan = fan; } public void setNetcard(String netcard) { this.netcard = netcard; } } public class Test { public static void main(String[] args) { ComputerBuilder cb = new ComputerBuilder(); Computer c = cb.setMotherboard("华硕主板").setCpu("酷睿8代").setFan("cpu自带的风扇").setHarddisk("500g").build(); System.out.println(c); } } // 建造者设计模式的第二种形态: 参考effective java 第二条2 :当类的属性过多时,就使用建造者设计模式的第二种形态