视频链接:https://www.bilibili.com/video/BV1eK4y1C7zi/
建造者模式
建造者模式也是属于创建型模型,是23种GOF之一。
建造者模式适用于一个复杂的对象的建造,而且在建造的过程中,客户端不必知道产品内部组成的细节。
这里的表示,我们用一个具体的例子来说明
具体建造者(ConcreteBuilder):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。
指挥者(Director):指挥并构造一个使用Builder接口的对象。
产品(Product):表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
我们这里有一需求
需求: 定义一个电脑类,电脑有很多属性,并且实例化电脑类的对象,以及给该对象赋值。
我们先不用构造者模式来实现一下
public class Computer{ private String cpu; private String gpu; private String memery; 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 getMemery() { return memery; } public void setMemery(String memery) { this.memery = memery; } public String getHd() { return hd; } public void setHd(String hd) { this.hd = hd; } @Override public String toString() { return "Computer{" + "cpu='" + cpu + '\'' + ", gpu='" + gpu + '\'' + ", memery='" + memery + '\'' + ", hd='" + hd + '\'' + '}'; } } // 测试 public class BuilderTest { public static void main(String[] args) { Computer computer = new Computer(); computer.setCpu("i5 9300H"); computer.setGpu("gtx1650"); computer.setMemery("16G"); computer.setHd("256ssd + 1T机械"); System.out.println(computer); } } /** * 我们先不用建造者模式,看看会有什么问题?? * 1. 客户端程序,在实例化好产品之后,必须为该对象的每一个属性赋值,这样对客户端程序员来说,太复杂了,需要了解compter类的细节 * 2. 违反了迪米特原则(最少知道原则) * 3. 客户端程序new出来computer对象不能立刻使用,需要设置很多属性 * * 相当于你去买电脑,商家不是把电脑成品直接给你,而是给你一堆零件,让你自己组装 * * 建造者模式与工厂模式的区别: * 工厂模式,都是直接实例化出一个类的对象即可。 * 建造者模式,是在实例化出类的对象之后,还要给该对象每一个属性赋值! */
结果
我们改进一下代码
/** * 电脑建造者类,建造者类,必须关联电脑产品 * 关联:一个类的对象,作为另一个类的对象成员 */ public class ComputerBuilder { private Computer computer = new Computer(); public Computer build(){ computer.setCpu("i7 8750HK"); computer.setGpu("RTX2080"); computer.setMemery("32G"); computer.setHd("512ssd + 2T机械"); return computer; } } //如果不同客户有不同需求呢? public class V1Test { public static void main(String[] args) { // 创建一个建造者 ComputerBuilder computerBuilder = new ComputerBuilder(); // 玩游戏 Computer computer = computerBuilder.build(); System.out.println(computer); // 开发 Computer computer2 = computerBuilder.build(); System.out.println(computer2); // 办公 Computer computer3 = computerBuilder.build(); System.out.println(computer3); } } /** * 目前这种写法还不是建造者模式,目前的优点: * 1. 客户端程序员需要一个产品时,直接向建造者要即可,建造者封装了电脑建造的复杂过程 * * 目前缺点: * 1. 封装的太过了,无论客户是什么需求,都是采用最高的配置 * 这相当于你去买电脑,不管你是买来干嘛的,商家都会给你配置最贵的电脑! * */
结果
这也不符合常理,我们再改进一下。
创建三个不同的建造者
/** * 电脑建造者类,建造者类,必须关联电脑产品 * 关联:一个类的对象,作为另一个类的对象 */ public class AdvancedComputerBuilder { private Computer computer = new Computer(); public Computer build(){ computer.setCpu("i7 8750HK"); computer.setMemery("32G"); computer.setHd("512ssd + 2T机械"); return computer; } } public class MiddleComputerBuilder { private Computer computer = new Computer(); public Computer build(){ computer.setCpu("i7 7700hq"); computer.setGpu("gtx1060"); computer.setMemery("16G"); computer.setHd("256ssd + 1T机械"); return computer; } } public class LowComputerBuilder { private Computer computer = new Computer(); public Computer build(){ computer.setCpu("i5 7500u"); computer.setGpu("gtx940mx"); computer.setMemery("8G"); computer.setHd("1T机械"); return computer; } } public class V2Test { public static void main(String[] args) { // 玩游戏 AdvancedComputerBuilder advancedComputerBuilder = new AdvancedComputerBuilder(); Computer computer = advancedComputerBuilder.build(); System.out.println(computer); // 开发 MiddleComputerBuilder middleComputerBuilder = new MiddleComputerBuilder(); Computer computer2 = middleComputerBuilder.build(); System.out.println(computer2); // 办公 LowComputerBuilder lowComputerBuilder = new LowComputerBuilder(); Computer computer3 = lowComputerBuilder.build(); System.out.println(computer3); } } /** *针对不同的需求,我们需要创建不同的建造者,来分别生产不同配置的产品 * * 这仍不是建造者模式 * 优点: * 1. 可以根据客户端的不同需求,使用不同的建造者生产产品 * * 缺点: * 1. 我们发现多个建造者中的代码在重复!出现了重复代码 * 2. 建造过程不稳定,如何在某个建造者创建产品的过程中,漏掉了某一步,编译器也不会提示。没有标准 */
还不行,再改进一下。
我们将建造电脑的过程抽象出来定义一个接口,以后不管什么配置的电脑,都是按照这个步骤走,相当于定义了一套规范,将建造过程稳定下来。
public interface ComputerBuilder { void setCpu(); void setGpu(); void setMemery(); void setHd(); Computer build(); } public class AdvancedComputerBuilder implements ComputerBuilder{ private Computer computer = new Computer(); @Override public void setCpu() { computer.setCpu("i7 8750HK"); } @Override public void setGpu() { computer.setGpu("RTX2080"); } @Override public void setMemery() { computer.setMemery("32G"); } @Override public void setHd() { computer.setHd("512ssd + 2T机械"); } public Computer build(){ return computer; } } public 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 setMemery() { computer.setMemery("16G"); } @Override public void setHd() { computer.setHd("256ssd + 1T机械"); } public Computer build(){ return computer; } } public class LowComputerBuilder implements ComputerBuilder{ private Computer computer = new Computer(); @Override public void setCpu() { computer.setCpu("i5 7500u"); } @Override public void setGpu() { computer.setGpu("gtx940mx"); } @Override public void setMemery() { computer.setMemery("8G"); } @Override public void setHd() { computer.setHd("1T机械"); } public Computer build(){ return computer; } }
public class V3Test { public static void main(String[] args) { // 玩游戏 AdvancedComputerBuilder advancedComputerBuilder = new AdvancedComputerBuilder(); advancedComputerBuilder.setCpu(); advancedComputerBuilder.setGpu(); advancedComputerBuilder.setMemery(); advancedComputerBuilder.setHd(); Computer computer = advancedComputerBuilder.build(); System.out.println(computer); // 开发 MiddleComputerBuilder middleComputerBuilder = new MiddleComputerBuilder(); middleComputerBuilder.setCpu(); middleComputerBuilder.setGpu(); middleComputerBuilder.setMemery(); middleComputerBuilder.setHd(); Computer computer2 = middleComputerBuilder.build(); System.out.println(computer2); // 办公 LowComputerBuilder lowComputerBuilder = new LowComputerBuilder(); lowComputerBuilder.setCpu(); lowComputerBuilder.setGpu(); lowComputerBuilder.setMemery(); lowComputerBuilder.setHd(); Computer computer3 = lowComputerBuilder.build(); System.out.println(computer3); } } /** *创建一个建造者的抽象接口,把制作产品的具体步骤稳定下来。 * 我们让建造者类,去实现建造者接口,接口中的方法步骤,类必须都要实现,少一个则会报错 * * 优点: * 建造者类中的建造过程是稳定的。不会漏掉某一步!!这样客户端想扩展建造者时,也不会漏掉某一步 * * 缺点: * 1. 代码依然重复 * 2. 现在又变成了客户端自己配电脑,又违反了迪米特法则。 * (相当于你去买电脑,虽然不用你亲自组装电脑,但是必须“指挥”那个装机的人,该装。。该装什么。。) */
又变成了客户端自己配电脑,又违反了迪米特法则!!!
下面是我们真正的建造者模式了
public class Director { public Computer build(ComputerBuilder cb){ cb.setCpu(); cb.setGpu(); cb.setMemery(); cb.setHd(); return cb.build(); } } public class V4Test { public static void main(String[] args) { AdvancedComputerBuilder advancedComputerBuilder = new AdvancedComputerBuilder(); MiddleComputerBuilder middleComputerBuilder = new MiddleComputerBuilder(); LowComputerBuilder lowComputerBuilder = new LowComputerBuilder(); Director director = new Director(); // 玩游戏 Computer computer = director.build(advancedComputerBuilder); System.out.println(computer); // 开发 Computer computer2 = director.build(middleComputerBuilder); System.out.println(computer2); // 办公 Computer computer3 = director.build(lowComputerBuilder); System.out.println(computer3); } } /** *这就是建造者模式 * 优点: * 1. 创建对象的过程是稳定不变的 * 2. 创建对象的过程只写了一次,没有重复代码(指挥者完成) * 3. 当需要扩展指挥者的时候,不用修改之前的代码,符合开闭原则 * * * 建造者模式与工厂模式的区别 * 工厂模式只需要一个简单的new,new出产品即可。 * 建造者更注重,在new出产品之后的,为产品赋值的过程! */
这就是我们的建造者模式,显然它是符合开闭原则的,假如一个客户需要中高配的电脑,我们只需要新建一个中高配电脑的builder,去实现ComputerBuilder接口,再传入Directer类build就行了,不需要改变之前的代码。
而一开始说到的表示,就是这这几个不同配置电脑的建造者,LowComputerBuilder,MiddleComputerBuilder和AdvancedComputerBuilder
最后来说下建造者模式与工长模式的区别:
1.工厂模式只需要一个简单的new,new出产品即可。
2.建造者更注重,在new出产品之后的,为产品赋值的过程