大家好✋,我是知识汲取者😄,今天给大家带来一篇有关建造者模式的学习笔记。众所周知能够熟练使用设计模式是一个优秀程序猿的必备技能,当我们在项目中选择一个或多个合适的设计模式,不仅能大大提高项目的稳健性、可移植性、可维护性,同时还能让你的代码更加精炼,具备艺术美感。
本文将详细讲解建造者模式的优点、缺点、实现方式和注意事项(干货满满哦😉),相信您花个十分钟就能快速了解并掌握建造者模式的使用,让您向架构师更进一步。话不多说,大家抓紧时间上车吧😈
推荐阅读:
什么是建造者模式?
建造者模式(Builder Pattern)是一种创建型模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
建造者模式的作用:将复杂对象的构建和表示进行分离(变与不变的分离),从而能够精细化控制对象的创建过程
建造者模式的优缺点
优点:
……
缺点:
……
建造者模式的适用场景:
……
Java中的应用:Java中的 StringBuilder就是使用了建造者模式,再比如DomcumetBuilder、SqlSessionFactoryBuilder等都使用了建造者模式(一般带有Builder的都是使用建造者模式来创建对象的)
生活中的应用:去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"
建造者模式的角色划分:
抽象建造者(Builder):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类方法是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口
具体建造者(Concrete Builder):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象
指挥者(Director):指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象(也可以通过配置文件和反射机制),然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。
它主要有两个作用:
具体产品(Concrete Product):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程
示例:
问题描述:
Sunny软件公司欲开发一个视频播放软件,为了给用户使用提供方便,该播放软件提供了四种显示模式:
- 网络模式拥有:主窗口、控制条、菜单、播放列表、收藏列表
- 完整模式拥有:主窗口、控制条、菜单、播放列表
- 记忆模式拥有:主窗口+控制条+收藏列表
- 精简模式只含有:主窗口、控制条

Step1:创建具体产品
Soft
package com.hhxy.pojo;
/**
* @author ghp
* @date 2022/9/29
* @Title
* @description
*/
public class Soft {
/**
* menu 菜单
* playList 播放列表
* window 主窗口
* control 控制条
* collection 收藏列表
*/
private String menu;
private String playList;
private String window;
private String control;
private String collection;
//由于篇幅有限,get、set、toString和构造方法都进行了省略,详细代码请参考Gitee或Github上的代码仓库
}
Step2:创建抽象建造者
package com.hhxy.builder;
import com.hhxy.pojo.Soft;
/**
* @author ghp
* @date 2022/9/29
* @Title 视频播放软件软件建造者
* @description
*/
public abstract class SoftBuilder {
//要被构建的复杂对象
private Soft soft = new Soft();
/**
* 让指挥者和具体建造者能够获取Soft对象
*/
protected Soft getSoft(){
return soft;
}
/**
* 建造主窗口
*/
public abstract void builderWindow();
/**
* 建造控制条
*/
public abstract void builderControl();
/**
* 建造菜单
*/
public abstract void builderMenu();
/**
* 建造播放列表
*/
public abstract void builderPlayList();
/**
* 建造收藏列表
*/
public abstract void builderCollection();
/**
* 钩子方法,用来控制子类的行为
*/
public boolean isBuilderMenu(){
return false;
}
public boolean isBuilderPlayList(){
return false;
}
public boolean isBuilderCollection(){
return false;
}
}
Step3:创建具体建造者
1)CompleteSoftBuilder(完整模式):
package com.hhxy.builder.child;
import com.hhxy.builder.SoftBuilder;
/**
* @author ghp
* @date 2022/9/29
* @Title 完整模式建造者
* @description 主窗口+控制条+播放列表+菜单
*/
public class CompleteSoftBuilder extends SoftBuilder {
/**
* 重写钩子方法,因为该显示模式不含有收藏列表(Collection)
*/
@Override
public boolean isBuilderCollection() {
return true;
}
/**
* 建造主窗口
*/
@Override
public void builderWindow() {
getSoft().setWindow("主窗口");
}
/**
* 建造控制条
*/
@Override
public void builderControl() {
getSoft().setControl("控制条");
}
/**
* 建造菜单
*/
@Override
public void builderMenu() {
getSoft().setMenu("菜单");
}
/**
* 建造播放列表
*/
@Override
public void builderPlayList() {
getSoft().setPlayList("播放列表");
}
/**
* 建造收藏列表
*/
@Override
public void builderCollection() {
getSoft().setCollection("收藏列表");
}
}
2)InternetSoftBuilder、3)MemoerySoftBuilder、4)StreamlineSoftBuilder
和上面代码类似,具体代码请参考Gitee或Github上的代码仓库,略……
Step4:创建指挥者
package com.hhxy.builder;
import com.hhxy.pojo.Soft;
/**
* @author ghp
* @date 2022/9/29
* @Title 指挥者
* @description 用来调度软件各组件的装配
*/
public class SoftDirector {
/**
* 未Soft产品装配各属性
* @param softBuilder 通过配置文件的读取可以获得该对象
* @return 具体产品
*/
public static Soft construct(SoftBuilder softBuilder) {
softBuilder.builderWindow();
softBuilder.builderControl();
if (!softBuilder.isBuilderMenu()) {
softBuilder.builderMenu();
}
if (!softBuilder.isBuilderCollection()) {
softBuilder.builderCollection();
}
if (!softBuilder.isBuilderPlayList()) {
softBuilder.builderPlayList();
}
return softBuilder.getSoft();
}
}
Step5:编写配置文件
soft-config.xml:
<config>
<builderName>com.hhxy.builder.child.StreamlineSoftBuilderbuilderName>
<builderName>com.hhxy.builder.child.CompleteSoftBuilderbuilderName>
<builderName>com.hhxy.builder.child.InternetSoftBuilderbuilderName>
<builderName>com.hhxy.builder.child.MemorySoftBuilderbuilderName>
<builderName>testbuilderName>
config>
Step6:编写配置文件读取类
ReadSoftConfig:
package com.hhxy.read;
import com.hhxy.builder.SoftBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.lang.reflect.Constructor;
/**
* @author ghp
* @date 2022/9/29
* @Title
* @description
*/
public class ReadSoftConfig {
public static SoftBuilder getSoftBuilder(){
try{
//1、将配置文件加载到内存中,获取DOM对象
//1.1 获取DOM解析器工厂对象DocumentBuilderFactory,用于创建DOM解析器
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//1.2 获取DOM解析器DocumentBuilder
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//1.3 加载配置文件
// Document document = documentBuilder.parse(new FileInputStream("Factory/src/car-config.xml"));
//让代码和模块名进行解耦,比上面那种方法更优
Document document = documentBuilder.parse(ReadSoftConfig.class.getResourceAsStream("/soft-config.xml"));
//2、获取配置文件中的数据
//2.1 从DOM中获取指定的结点的结点列表
NodeList nodeList = document.getElementsByTagName("builderName");
//2.2 获取指定位置的结点
Node classNode = nodeList.item(2).getFirstChild();
//2.3 获取指定结点中的数据(排除空格)
String builderName = classNode.getNodeValue().trim();
//2.4 获取类名并输出
int index = builderName.lastIndexOf(".");
String className = builderName.substring(index + 1);
System.out.print(className+"=");
//3、使用反射获取获取SoftBuilder对象
//3.1 获取类对象
Class cls = Class.forName(builderName);
//3.2 获取该类对象的构造器对象
Constructor constructor = cls.getDeclaredConstructor();
//3.3 暴力反射,防止构造器私有化导致无法创建对象
constructor.setAccessible(true);
//3.4 获取工厂对象
SoftBuilder softBuilder = (SoftBuilder) constructor.newInstance();
//4、返回通过配置文件获取的工厂对象
return softBuilder;
} catch (Exception e) {
//如果异常就打印异常信息,同时返回一个空
e.printStackTrace();
throw new RuntimeException("未找到该工厂类,请检查配置文件或者添加一个工厂类!");
}
}
}
Step7:测试
package com.hhxy.test;
import com.hhxy.builder.SoftBuilder;
import com.hhxy.builder.SoftDirector;
import com.hhxy.pojo.Soft;
import com.hhxy.read.ReadSoftConfig;
/**
* @author ghp
* @date 2022/9/29
* @Title 测试类
* @description 用于测试建造者模式
*/
public class Test {
public static void main(String[] args) {
/*
方式一:直接通过new获取具体建造者对象
Soft soft = SoftDirector.construct(new StreamlineSoftBuilder());
Soft soft = SoftDirector.construct(new StreamlineSoftBuilder());
Soft soft = SoftDirector.construct(new StreamlineSoftBuilder());
Soft soft = SoftDirector.construct(new StreamlineSoftBuilder());
*/
//方式二:通过读取配置文件获取具体建造者对象,这种方式降低了代码的耦合度,同时也很方便测试
SoftBuilder softBuilder = ReadSoftConfig.getSoftBuilder();
Soft soft = SoftDirector.construct(softBuilder);
System.out.println(soft);
}
}
测试结果:

备注:可能你会觉得这里直接用new来创建要简单很多,那是由于这个例子中的对象过于简单,在实际工作中,对象是相当复杂的,而建造者模式就是用来解决复杂对象的创建的,简单对象还是推荐直接使用new来创建,这里只是进行一个创建者模式的示范
自此,文章就结束了,如果觉得本文对你有一丢丢帮助的话😄,欢迎点赞👍+评论✍,您的支持将是我写出更加优秀文章的动力O(∩_∩)O

上一篇:每日一个设计模式之【工厂模式】
下一篇:每日一个设计模式之【适配器模式】
参考文章:
- [建造者模式 | 菜鸟教程](https://www.runoob.com/design-pattern/builder-pattern.html#:~:text=建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 一个,Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。)
- 一篇打通架构设计,Java设计模式10,建造者模式
- Java设计模式之创建型:建造者模式
- 建造者模式(Builder Pattern)总结
在次致谢