设计模式-建造者模式(代码实现、源码级别应用、使用场景)
提示:建造者模式的代码实现、建造者模式的使用场景、建造者模式源码级别的应用、建造者模式的优点、建造者模式的几种变形写法
文章目录
- 前言
- 一、定义
- 二、类图
- 三、代码实现
- 3.1、建造者模式-第一种模式
- 1、要建造的对象:
- 2、对这个builder的抽象
- 3.对抽象出来的方法的第一种实现
- 4、是控制建造者模式中,具体的先builder啥,再builder啥的类
- 3.2、建造者模式-第二种模式(第一种方式)
- 1、代码
- 2、测试类
- 3、建造者模式-第二种模式(一种变种)
- 1、代码
- 2、测试类
- 四、应用场景
- 五、源码中的应用:
- 总结
前言
随着时间的推移,我现在越来越感觉自己的代码不够优雅了,相信有一部分博友跟我有同样的困扰,因此决定再学习记录一下相关的设计模式。今天就介绍一下设计模式-建造者模式
一、定义
为了对应部分复杂对象,而创建出来的方法。(通常是跟一些不可变对象配合使用)
字段属性有一个顺序的要求,必须先做了哪个,然后才能做哪个。
二、类图
- 右下角的product 可以简单的理解为,是一个复杂的对象。(要builder的对象)
- builder是这个对象抽象出去的一些方法。
- concreteBuilder是builder的具体的某一个实现
- 具体的builder的逻辑,是由Director来控制(比如说第一步做哪些工作,第二部做哪些工作)
三、代码实现
3.1、建造者模式-第一种模式
1、要建造的对象:
package com.zheng.builder;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author: ztl* @date: 2024/09/22 22:33* @desc: 这里指复杂对象*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {private String productName;private String companyName;private String part1;private String part2;private String part3;// ...
}
2、对这个builder的抽象
模式1中,对这个builder的抽象(就是要建造的复杂对象中,抽出来一部分公共的方法)
package com.zheng.builder.mode1;import com.zheng.builder.Product;/*** @author: ztl* @date: 2024/09/22 22:36* @desc: 模式1中,对这个builder的抽象(就是要建造的复杂对象中,抽出来一部分公共的方法)*/
public interface ProductBuilder {void builderProductName(String productName);void builderCompanyName(String companyName);void builderPart1(String part1);void builderPart2(String part2);void builderPart3(String part3);// 返回要建造的对象(上面不是set某写数学的逻辑嘛,最后肯定要返回一个要建造的对象)Product build();
}
3.对抽象出来的方法的第一种实现
代码如下(示例):
package com.zheng.builder.mode1;import com.zheng.builder.Product;/*** @author: ztl* @date: 2024/09/22 22:38* @desc: 抽象出来的方法中的,一个具体的实现*/
public class DefaultProductBuilder implements ProductBuilder{private String productName;private String companyName;private String part1;private String part2;private String part3;@Overridepublic void builderProductName(String productName) {this.productName = productName;}@Overridepublic void builderCompanyName(String companyName) {this.companyName = companyName;}@Overridepublic void builderPart1(String part1) {this.part1 = part1;}@Overridepublic void builderPart2(String part2) {this.part2 = part2;}@Overridepublic void builderPart3(String part3) {this.part3 = part3;}@Overridepublic Product build() {// 返回一个有参构造(这也可以理解,你类中有这些属性,你不返回有参构造,还能返回无参构造嘛)return new Product(productName,companyName,part1,part2,part3);}
}
4、是控制建造者模式中,具体的先builder啥,再builder啥的类
package com.zheng.builder.mode1;import com.zheng.builder.Product;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author: ztl* @date: 2024/09/22 22:41* @desc: 是控制建造者模式中,具体的先builder啥,再builder啥的类*/@Data
@AllArgsConstructor
@NoArgsConstructor
public class Director {private ProductBuilder builder;/*** 具体的builder步骤,先干嘛,在干嘛,最后干嘛* @return*/public Product makeProduct(String productName,String companyName,String part1,String part2,String part3){// 先构建companyName,builder.builderCompanyName(companyName);// 有companyName了再构建productName,builder.builderProductName(productName);builder.builderPart1(part1);builder.builderPart2(part2);builder.builderPart3(part3);// ...// 这里看的build中没任何参数,其中他的build方法会把所有的属性都带上return builder.build();}
}
3.2、建造者模式-第二种模式(第一种方式)
1、代码
package com.zheng.builder.mode1;import com.zheng.builder.Product;/*** @author: ztl* @date: 2024/09/22 22:38* @desc: 抽象出来的方法中的,第二个具体的实现*/
public class TwoProductBuilder implements ProductBuilder{private String productName;private String companyName;private String part1;private String part2;private String part3;@Overridepublic void builderProductName(String productName) {this.productName = productName+"123";}@Overridepublic void builderCompanyName(String companyName) {this.companyName = companyName;}@Overridepublic void builderPart1(String part1) {this.part1 = part1+"123";}@Overridepublic void builderPart2(String part2) {this.part2 = part2;}@Overridepublic void builderPart3(String part3) {this.part3 = part3;}@Overridepublic Product build() {// 返回一个有参构造(这也可以理解,你类中有这些属性,你不返回有参构造,还能返回无参构造嘛)return new Product(productName,companyName,part1,part2,part3);}
}
2、测试类
package com.zheng.builder;import com.zheng.builder.mode1.DefaultProductBuilder;
import com.zheng.builder.mode1.Director;
import com.zheng.builder.mode1.ProductBuilder;
import com.zheng.builder.mode1.TwoProductBuilder;/*** @author: ztl* @date: 2024/09/22 22:34* @desc:*/
public class BuilderTest {public static void main(String[] args) {// 对于Product这个复杂对象,我们正常的构建怎么构建呢:Product product = new Product();product.setProductName("00");product.setCompanyName("..");// ...// 模式1的建造者demo:ProductBuilder defaultProductBuilder = new DefaultProductBuilder();// 建造者模式中不是需要一个具体的实现嘛,这是就是其中一个具体实现,你可以有第二个具体实现Director director = new Director(defaultProductBuilder);Product product1 = director.makeProduct("pname", "cname", "par1", "2", "4");System.out.println(product1); // Product(productName=pname, companyName=cname, part1=par1, part2=2, part3=4)// 模式1的建造者demo2:ProductBuilder twoProductBuilder = new TwoProductBuilder();// 建造者模式中不是需要一个具体的实现嘛,这是就是其中一个具体实现,你可以有第二个具体实现Director director2 = new Director(twoProductBuilder);Product product2 = director2.makeProduct("pname", "cname", "par1", "2", "4");
// System.out.println(product2); // Product(productName=pname123, companyName=cname, part1=par1123, part2=2, part3=4)}
}
3、建造者模式-第二种模式(一种变种)
建造者模式的一个变种,当没那么复杂的时候,可以用这个方式(通常是配合不可变对象一起使用):
1、代码
package com.zheng.builder.mode2;/*** @author: ztl* @date: 2024/09/23 22:24* @desc: 建造者模式变种,的测试类*/
public class Product2Test {public static void main(String[] args) {// 可以:Product2 build = new Product2.Builder().companyName("1").productName("332").build();System.out.println(build);// 也可以:Product2.Builder builder = new Product2.Builder();builder.productName("nihap");builder.part1("1");builder.part2("3");Product2 build2 = builder.build();System.out.println(build2);}
}
2、测试类
package com.zheng.builder.mode2;/*** @author: ztl* @date: 2024/09/23 22:24* @desc: 建造者模式变种,的测试类*/
public class Product2Test {public static void main(String[] args) {// 可以:Product2 build = new Product2.Builder().companyName("1").productName("332").build();System.out.println(build);// 也可以:Product2.Builder builder = new Product2.Builder();builder.productName("nihap");builder.part1("1");builder.part2("3");Product2 build2 = builder.build();System.out.println(build2);}
}
四、应用场景
1.需要生成的对象具有复杂的内部结构
2.需要生成的对象内部属性本身互相依赖
3.与不可变对象配合使用
优点:
1.建造者独立,易扩展
2.便于控制细节风险
五、源码中的应用:
org.springframework.web.servlet.mvc.method.RequestMappingInfo;
org.springframework.beans.factory.support.BeanDefinitionBuilder;
总结
其实我总感觉这些设计模式,都一个套路:抽出来公共的,然后去复用公共的。