本文由老王拼装电脑-builder设计模式介绍,详细介绍了builder模式的基本概念和实现代码。为了便于理解建造者模式,我们将对典型案例进行介绍。最后,比较工厂模式和建造者模式的区别,我们在实际使用中可以更加灵活的选择设计模式。读者可以拉取完整代码在本地学习,测试通过后将代码上传至码云。1、问题引出:老王家里需要组装一台笔记本电脑,但到底是先买办公本还是游戏本,老王和小王吵了起来。因为如果需要两台电脑,那么CPU、内存……一系列配件的采购不仅需要专业知识,而且办公本和游戏本的配置也是不一样的。对于老王和小王来说,这些都是很复杂的问题。就这样,他们从家里一路吵到电脑店……销售人员给了他们一个想法,如果把配置电脑的工作交给一个专业的指挥,然后让指挥把购买的东西交出来。配件到特定游戏笔记本和办公笔记本的采购人员,让您只需要将需要的资料交给指挥官,而无需关注采购和组装过程。这时候老大又出来补充了一句。为了避免指挥官依赖具体的采购人员,可以将采购人员进一步抽象。二、模式的概念和使用其实设计模式中涉及到的问题的解决方案就是建造者模式,这也是创造型设计模式中的最后一个。建造者模式将对象的创建过程与其表示分离,调用者通过conductor调用方法构造对象,使调用者不再关心对象的构造过程,构造对象的具体过程可以根据传入类型。老王和小王相当于客户的来电者。那些命令购买计算机的人正在调用方法。他们的最终目标是构建复杂的对象(组装计算机)。老王和小王只需要将相关资料交给指挥官就可以了。售票员直接把成品递给他,具体细节小王和老王不用关心。这种设计模式包括四种角色:产品、建造者、特定建造者和指挥官。为了简化实际使用,四个角色并不是都需要,往往只保留具体的构建过程。下面以老王搭建的电脑为例,看看具体的实现代码:productclass(computer)/***product*@authortcy*@Date30-07-2022*/publicclassComputer{privateStringCPU;私有字符串GPU;私有字符串内存;私有字符串主板;私有字符串硬盘;publicvoidsetCPU(StringCPU){this.CPU=CPU;}publicvoidsetGPU(StringGPU){this.GPU=GPU;}publicvoidsetMemory(Stringmemory){this.memory=memory;}publicvoidsetMotherboard(Stringmotherboard){this.motherboard=motherboard;}publicvoidsetHardDisk(StringhardDisk){this.hardDisk=hardDisk;}@OverridepublicStringtoString(){return"youhaveacomputer:\n"+"\tCPU:"+CPU+"\n"+"\tGPU:"+GPU+"\n"+"\t内存:"+内存+"\n"+"\t主板:"+主板+"\n"+"\thardDisk:"+hardDisk+"\n";}Computer(){}Computer(StringCPU,StringGPU,Stringmemory,Stringmotherboard,StringhardDisk){this.CPU=CPU;this.GPU=GPU;this.memory=内存;this.motherboard=motherboard;this.hardDisk=hardDisk;}}abstractbuilder:/***abstractbuilder*@authortcy*@Date30-07-2022*/publicabstractclassAbstractComputerBuilder{protectedComputercomputer=newComputer();publicabstractvoidCPU();publicabstractvoidGPU();publicabstractvoidmemory();ComputergetComputer();}具体构建器1:/***具体构建器2*@authortcy*@Date30-07-2022*/publicclassOfficeComputerBuilderextendsAbstractComputerBuilder{@OverridepublicvoidCPU(){computer.setCPU("i7-7700k");}@OverridepublicvoidGPU(){computer.setGPU("GTX1050Ti");}@Overridepublicvoidmemory(){computer.setMemory("32GB");}@Overridepublicvoidmotherboard(){computer.setMotherboard("ASUSB560M-PLUS");}@OverridepublicvoidhardDisk(){computer.setHardDisk("1TBSSD");}@OverridepublicComputergetComputer(){System.out.println("获取办公电脑...");归还电脑;}}Concretebuilder2(gamebookassembler):/***Concretebuilder1*@authortcy*@Date30-07-2022*/publicclassGameComputerBuilderextendsAbstractComputerBuilder{@OverridepublicvoidCPU(){computer.setCPU(“i9-12900K”);}@OverridepublicvoidGPU(){computer.setGPU("RTX3090Ti");}@Overridepublicvoidmemory(){computer.setMemory("64GB");}@Overridepublicvoidmotherboard(){computer.setMotherboardd("Z590AORUS大师");}@OverridepublicvoidhardDisk(){computer.setHardDisk("2TBSSD");}@OverridepublicComputergetComputer(){System.out.println("获得一台游戏电脑......");归还电脑;}}Director:/***Director*@authortcy*@Date30-07-2022*/publicclassDirector{privateAbstractComputerBuilderbuilder;publicDirector(AbstractComputerBuilderbuilder){这个。建造者=建造者;}publicComputerconstruct(){builder.CPU();建造者.GPU();计算机产品=builder.getComputer();退回产品;}}Caller(老王和小王):/***@authortcy*@Date30-07-2022*/publicclassClient{publicstaticvoidmain(String[]args){newDirector(newGameComputerBuilder())。构造();新总监(新OfficeComputerBuilder()).construct();}这样,对于老王(调用者)来说,如果他需要办公本,他会直接告诉指挥官他需要办公本,指挥官会调用对应的采购员。老王不需要知道具体的采购流程。这同样适用于王。为了让读者更清楚地理解,我们将对Jdk、Mybatis、Spring中的典型应用进行介绍和讲解。三、典型应用1、Jdk应用和Lombok应用①StringBuilder是使用的builder模式。StringBuilder类继承了AbstractStringBuilder,每次我们调用append方法时,我们都将字符附加到AbstractStringBuilder类中的变量值。所以此时AbstractStringBuilder对应的是抽象的建造者,StringBuilder是具体的建造者,String对象就是我们需要的产物。但是这时候我们并没有找到主任。其实此时StringBuilder类也充当了Director的角色,它的toString()方法返回的是最终的String对象。②当我们使用Lombok时,实体会被注解@Builder。为实体添加@Builder,实际上生成了一个内部类。反编译后,我们可以看到内部类的具体代码。publicstaticComputer.ComputerBuilderbuilder(){returnnewComputer.ComputerBuilder();}publicstaticclassComputerBuilder{privateStringCPU;私有字符串GPU;私有字符串内存;私有字符串主板;私有字符串硬盘;ComputerBuilder(){}//链式调用----------------startpublicComputer.ComputerBuilderCPU(StringCPU){this.CPU=CPU;归还这个;}publicComputer.ComputerBuilderGPU(StringGPU){this.GPU=GPU;归还这个;}publicComputer.ComputerBuildermemory(Stringmemory){this.memory=memory;归还这个;}publicComputer.ComputerBuildermotherboard(Stringmotherboard){this.motherboard=motherboard;归还这个;}publicComputer.ComputerBuilderhardDisk(StringhardDisk){this.hardDisk=hardDisk;归还这个;}//链式调用----------------endpublicComputerbuild(){returnnewComputer(this.CPU,this.GPU,this.memory,this.motherboard,this.hardDisk);}publicStringtoString(){return"Computer.ComputerBuilder(CPU="+this.CPU+",GPU="+this.GPU+",memory="+this.memory+",motherboard="+this.motherboard+",hardDisk="+this.hardDisk+")";}}staticinnerclass其实充当了builder,指挥官的角色,在创建对象的时候直接调用entity.builder()会生成对象然后调用集合链调用赋值Computer.ComputerBuildercomputerBuilder=Computer.builder();computerBuilder.CPU("it-9000").内存("500m");这大大简化了对象的创建过程,也可以通过链式调用进行赋值。2.在Mybatis中的应用SqlSessionFactoryBuilder在MyBatis中使用的builder模式。每个基于MyBatis的应用程序都以SqlSessionFactory的实例为中心。SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从XML配置文件或预先定制的Configuration实例构建SqlSessionFactory实例。SqlSessionFactory是Mybatis需要的“产品”,而SqlSessionFactoryBuilder是从xml配置文件或Configuration中取出需要的信息,形成不用的对象的构建器。3.在Spring中的应用BeanDefinitionBuilder在Spring中BeanDefinition是一个复杂的对象,它是通过BeanDefinitionBuilder来创建的。在启动过程中,会通过BeanDefinitionBuilder一步步构建复杂的对象BeanDefinition,然后通过getBeanDefinition()方法获取BeanDefinition对象。拿到BeanDefinition后,注册到IOC容器中(存放在beanDefinitionMap中)。BeanDefinition是必需的“产品”,而BeanDefinitionBuilder是构建器。4.总结我们可以看出,工厂模式和建造者模式都属于创造型设计模式,最终目的是创造对象。那么它们之间有什么区别呢?实际使用中如何选择?其实对比我们之前的文章和工厂模式的例子,我们举的例子是老王采购了产品A、B、C,名字看起来像是量产的,没讲搭建过程,就像工厂生产产品一样。相同的。我们在这篇文章中举的例子就是计算机这样一个具体而复杂的产品,我们更关注每一步的组装过程。看到这里,我们就能隐约感觉到它们之间的区别了。①工厂模式不需要分步创建对象,得到的产品对象完全一样;而builder模式会因为构建顺序的不同而产生不同的产物(如上面的StringBuilder);②建造者模式更适合构建复杂的对象,可以逐步丰富产品特性,而工厂模式要求在创建对象时需要设置所有属性;如果只看概念性的东西,还是有点苍白,我们举一个典型的Spring中的例子来对比一下。Spring中的FactoryBean接口使用工厂方法模式。FactoryBean是工厂bean。我们可以通过实现FactoryBean接口并重写其getObject()方法来自定义工厂bean,自定义我们需要生成的bean。Spring本身有很多FactoryBean的实现。它们隐藏了一些复杂bean的实例化细节。调用者不需要关注那些复杂的bean是如何创建的。他们只需要通过这个工厂bean来获取它们!而BeanDefinition是一个复杂的、高度个性化的bean,里面包含了很多Bean的信息,比如类名、作用域、属性、构造函数参数列表、依赖bean、是否是单例类、是否是懒加载等。在其实就是将Bean的定义信息存放在BeanDefinition的对应属性中,在创建过程中使用builder模式更合适。结合典型应用,认真理解建造者模式与工厂模式的区别,并参考软件设计的七大原则,在实际应用中更加灵活运用,而不是死记硬背。本文以五个创建模式结束。1.设计模式概述2.设计模式的工厂方法和抽象工厂3.设计模式的单例和原型读者一定要仔细理解它们之间的区别,最好把所有的代码都写出来加强理解。
