本文转载自微信公众号《JavaKeeper》,作者海星。转载本文请联系JavaKeeper公众号。简介BuilderPattern,中文翻译为建造者模式或建造者模式,也有人称之为建造者模式。构建器模式是一种创建型设计模式,使您能够逐步创建复杂的对象。它允许用户仅通过指定对象的类型和内容来构造复杂的对象,而用户无需了解具体的内部构造细节。定义:将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示。helloworld程序员么,首先上个helloworld热门身publicclassUser{privateLongid;privateStringname;privateIntegerage;//可选privateStringdesc;//可选privateUser(Builderbuilder){this.id=builder.id;this.name=builder.name;this.age=builder.age;this.desc=builder.desc;}publicstaticBuildernewBuilder(Longid,Stringname){returnnewBuilder(id,name);}publicLonggetId(){returnid;}publicStringgetName(){returnname;}publicIntegergetAge(){returnage;}publicStringgetDesc(){returndesc;}@OverridepublicStringtoString(){return"Builder{"+"id="+id+",name='"+name+'\''+",age="+age+",desc='"+desc+'\''+'}';}publicstaticclassBuilder{privateLongid;privateStringname;privateIntegerage;privateStringdesc;privateBuilder(Longid,Stringname){Assert.assertNotNull("标记不能为空",id);断言。assertNotNull("名称不能为空",name);this.id=id;this.name=name;}publicBuilderage(Integerage){this.age=age;returnthis;}publicBuilderdesc(Stringdesc){this.desc=desc;返回nthis;}publicUserbuild(){returnnewUser(this);}}publicstaticvoidmain(String[]args){Useruser=User.newBuilder(1L,"starfish").age(22).desc("test").build();System.out.println(user.toString());}}这段代码的优缺点是什么?主要优点:明确指定必选参数和可选参数,并在构造方法中进行验证;可以定义为immutableClass,初始化后属性字段的值不能改变;赋值代码更具可读性,哪个属性字段对应哪个值一目了然;支持链式方法调用,代码比调用Setter方法更简洁。主要缺点:代码量大,多定义一个Builder类,多定义一组属性字段,多实现一组赋值方法;运行效率低,需要先创建Builder实例,然后分配属性字段,再创建目标实例,最后复制属性字段。当然,上面的代码可以通过使用Lombok的@Builder来简化。如果我们只用三三二二参数,直接构造函数用set方法就可以了,就不需要用所谓的pattern了。高射炮打蚊子——不划算假设你有这么一个复杂的对象,在构造它的时候,需要对很多成员变量和嵌套对象进行繁琐的初始化工作。这段初始化代码通常深埋在一个构造函数中,其中包含许多难以理解的参数;甚至更糟的是,它散布在客户端代码的多个位置。这是构造函数模式发挥作用的时候。上面的例子其实是builder模式的简化版,只是为了方便类中各种参数的构造。而“严肃”的则与此有些不同,更倾向于使用相同的施工工艺。逐步创建不同的产品类别。继续拉~结构从UML图中可以看出有4个不同的角色。抽象生成器(Builder):创建一个由Product对象的每个组件指定的接口/抽象类。具体构建器(ConcreteBuilder):实现接口,构建和组装各个组件Director/Director类(Director):使用Builder接口构建一个对象。它负责调用适当的构建器来构建产品。director类一般与product类没有依赖关系,builder类直接与director类交互。产品(Product):一个具体的产品对象demo假设我是一个汽车厂,需求是可以造各种汽车(或者造电脑,盖房子,做煎饼,生成不同的文件TextBuilder,HTMLBuilder等,都是都是一样的道理)1.建造者(Builder)接口声明了所有类型建造者中通用的产品构造步骤publicinterfaceCarBuilder{voidsetCarType(CarTypetype);voidsetSeats(intseats);voidsetEngine(Engineengine);voidsetGPS(GPSgps);}2.具体的建造者(ConcreteBuilders)提供构建过程的不同实现EversetEnginepub){this.engine=engine;}@OverridepublicvoidsetGPS(GPSgps){this.gps=gps;}publicCargetResult(){returnnewCar(carType,seats,engine,gps);}}3.Products是最终生成的对象@this.seats=seats;this.engine=engine;this.gps=gps;}}4.导演(Director)类定义了构建步骤的调用顺序,使得具体的产品配置(导演类构建)可以被创建和重用的函数的参数是CarBuilder,但实际上并没有传入实例作为参数,因为CarBuilder是接口或者抽象类,无法生成对象实例。实际传入的是Builder的子类,制作内容根据子类的类型决定)publicclassDirector{publicvoidconstructSportsCar(CarBuilderbuilder){builder.setCarType(CarType.SPORTS_CAR);builder.setSeats(2);builder.setEngine(newEngine(2.0,0));builder.setGPS(newGPS());}publicvoidconstructCityCar(CarBuilderbuilder){builder.setCarType(CarType.CITY_CAR);builder.setSeats(4);builder.setEngine(newEngine(1.5,0));builder.setGPS(newGPS());}publicvoidconstructSUVCar(CarBuilderbuilder){builder.setCarType(CarType.SUV);builder.setSeats(4);builder.setEngine(newEngine(2.5,0));builder.setGPS(newGPS());}}5.客户端使用(最终结果从builder对象中获取,主管不知道最终产品类型)publicclassClient{publicstaticvoidmain(String[]args){Directordirector=newDirector();SportsCarBuilderbuilder=newSportsCarBuilder();director.constructSportsCar(builder);Carcar=builder.getResult();System.out.println(car.toString());}}适用场景适用场景其实是理解设计模式最重要的。只要知道这个业务场景需要什么模式就可以上网了~程序员可以使用建造者模式吗?避免重叠构造函数的出现假设你的构造函数中有N个可选参数,new各种实例会很麻烦,当你想用代码创建不同形式的产品(如石头)时,你需要多次重载构造函数或木屋)建造者模式可用。当您需要创建以类似方式制造且仅在细节上有所不同的各种形式的产品时,请使用构建器模式。使用生成器构建复合树或其他复杂对象。构建器模式允许您逐步构建您的产品。您可以延迟某些步骤而不影响最终产品。您甚至可以递归调用这些步骤,这在创建对象树时非常方便。VS抽象工厂抽象工厂模式实现了产品族的创建。产品系列是一系列产品:具有不同分类维度的产品组合。抽象工厂模式不需要关心抽象过程,只关心哪些产品由哪些工厂生产。能。建造者模式需要按照指定的蓝图建造产品,其主要目的是通过组装零配件来生产新产品。最后是设计模式。这个东西看简单的例子就明白了。主要是结合自己的业务思考如何应用,让系统设计的更加完善。了解每种模式后,你可以找到各种框架源代码或在github上。搜索相关内容,看看在实践中是如何应用的。参考refactoringguru.cn
