建造者模式
引言
建造者模式是一种创建型设计模式,它将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。该模式通过分步骤构建对象,最终提供完整的成品,特别适用于具有多个组成部分的复杂对象。建造者模式既能保证对象的完整性,又能提供灵活的构建方式,是处理复杂对象创建的优雅解决方案。
实际开发中的用途
在实际开发中,建造者模式常用于以下场景:
- 需要创建包含多个部件的复杂对象(如HTML文档、报表等)
- 对象的构建过程需要分步骤进行
- 需要不同的对象表示但构建过程相似
- 希望隔离复杂对象的创建和使用
该模式解决了直接使用构造函数或setter方法创建复杂对象时面临的参数过多、构建逻辑混乱等问题,使代码更加清晰可维护。
Spring源码中的应用
Spring框架中广泛使用了建造者模式,一个典型的例子是UriComponentsBuilder
类,用于构建URI组件。以下是Spring源码中的相关实现:
java
// Spring框架中的UriComponentsBuilder
public class UriComponentsBuilder implements UriBuilder, Cloneable {
private String scheme;
private String userInfo;
private String host;
private int port = -1;
private String path;
private final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
private String fragment;
// 私有构造函数
private UriComponentsBuilder() {
}
// 静态工厂方法
public static UriComponentsBuilder newInstance() {
return new UriComponentsBuilder();
}
public static UriComponentsBuilder fromUri(URI uri) {
return new UriComponentsBuilder().uri(uri);
}
// 各种构建方法
public UriComponentsBuilder scheme(String scheme) {
this.scheme = scheme;
return this;
}
public UriComponentsBuilder host(String host) {
this.host = host;
return this;
}
// 最终构建方法
public UriComponents build() {
return new UriComponents(scheme, userInfo, host, port, path, queryParams, fragment);
}
}
在这个实现中,UriComponentsBuilder
提供了流畅的API来逐步构建URI的各个部分,最后通过build()
方法生成不可变的UriComponents
对象。这种设计使得URI的构建过程既灵活又安全,同时保持了代码的清晰性。
开发中的示例
考虑一个用户信息构建场景,用户对象包含姓名、年龄、地址、电话等多个属性,其中某些属性是必填的,某些是可选的。使用建造者模式可以清晰地表达哪些属性是必需的,哪些是可选的,并确保最终构建的用户对象是完整且一致的。
在实际开发中,MyBatis-Plus代码生成器常用于:
- 快速生成Entity、Mapper、Service、Controller等基础代码
- 统一项目代码风格和规范
- 减少重复CRUD代码编写时间
- 支持自定义模板生成特定结构代码
建造者模式在此场景中完美解决了代码生成配置复杂、可选参数多、生成过程需要分步控制等问题。
MyBatis-Plus源码中的应用
MyBatis-Plus的AutoGenerator
类是建造者模式的典型实现。
以下是其核心源码结构:
java
public class AutoGenerator {
private DataSourceConfig dataSource;
private GlobalConfig globalConfig;
private PackageConfig packageInfo;
private StrategyConfig strategy;
private TemplateConfig template;
private InjectionConfig injectionConfig;
// 建造者方法
public AutoGenerator setDataSource(DataSourceConfig dataSource) {
this.dataSource = dataSource;
return this;
}
public AutoGenerator setGlobalConfig(GlobalConfig globalConfig) {
this.globalConfig = globalConfig;
return this;
}
// 其他配置方法...
// 执行生成
public void execute() {
// 生成逻辑实现...
}
}
MyBatis-Plus代码生成器是建造者模式的工业级实践典范。通过将复杂的代码生成过程分解为多个可配置的构建步骤,它既保证了生成代码的质量,又提供了极大的灵活性。在实际开发中:
- 对于标准CRUD代码生成,直接使用默认配置即可
- 对于特殊需求,可以通过自定义模板和策略配置灵活扩展
- 建造者模式使得配置过程直观且类型安全
- 与Spring Boot的整合使其更加易用
掌握这种建造者模式的应用,可以极大提升开发效率,同时保证项目代码风格的一致性。
SpringBoot代码使用案例
以下是完整的Spring Boot 整合MyBatis-Plus代码生成器的实现:
java
@Configuration
public class MybatisPlusGenerator {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
/**
* 代码生成器配置
*/
@Bean
public CommandLineRunner codeGenerator() {
return args -> {
// 1. 全局配置
GlobalConfig globalConfig = new GlobalConfig.Builder()
.outputDir(System.getProperty("user.dir") + "/src/main/java")
.author("BuilderPatternDemo")
.enableSwagger()
.dateType(DateType.TIME_PACK)
.commentDate("yyyy-MM-dd")
.build();
// 2. 数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(url, username, password)
.dbQuery(new MySqlQuery())
.schema("mybatis_plus_demo")
.typeConvert(new MySqlTypeConvert())
.build();
// 3. 包配置
PackageConfig packageConfig = new PackageConfig.Builder()
.parent("com.example.demo")
.moduleName("system")
.entity("entity")
.mapper("mapper")
.service("service")
.serviceImpl("service.impl")
.controller("controller")
.pathInfo(Collections.singletonMap(OutputFile.xml,
System.getProperty("user.dir") + "/src/main/resources/mapper"))
.build();
// 4. 策略配置
StrategyConfig strategyConfig = new StrategyConfig.Builder()
.addInclude("t_user", "t_order") // 要生成的表
.addTablePrefix("t_") // 表前缀过滤
.entityBuilder()
.enableLombok()
.enableChainModel()
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel)
.logicDeleteColumnName("is_deleted")
.versionColumnName("version")
.addSuperEntityColumns("id", "create_time", "update_time")
.formatFileName("%sEntity")
.mapperBuilder()
.enableBaseResultMap()
.enableBaseColumnList()
.formatMapperFileName("%sMapper")
.formatXmlFileName("%sMapper")
.serviceBuilder()
.formatServiceFileName("%sService")
.formatServiceImplFileName("%sServiceImpl")
.controllerBuilder()
.enableRestStyle()
.formatFileName("%sController")
.build();
// 5. 模板配置
TemplateConfig templateConfig = new TemplateConfig.Builder()
.disable(TemplateType.ENTITY)
.entity("/templates/entity.java")
.service("/templates/service.java")
.serviceImpl("/templates/serviceImpl.java")
.mapper("/templates/mapper.java")
.xml("/templates/mapper.xml")
.controller("/templates/controller.java")
.build();
// 6. 自定义配置
InjectionConfig injectionConfig = new InjectionConfig.Builder()
.beforeOutputFile((tableInfo, objectMap) -> {
// 生成前回调
})
.customMap(Collections.singletonMap("test", "MyBatis-Plus"))
.customFile(Collections.singletonMap("DTO.java", "/templates/entityDTO.java.ftl"))
.build();
// 7. 执行生成
new AutoGenerator(dataSourceConfig)
.global(globalConfig)
.packageInfo(packageConfig)
.strategy(strategyConfig)
.template(templateConfig)
.injection(injectionConfig)
.execute();
};
}
}
建造者模式的优势
- 配置清晰:每个配置项都有明确的构建方法,避免参数混乱
- 灵活性高:可以自由组合各种配置,满足不同需求
- 可读性强:链式调用使代码逻辑清晰易懂
- 扩展方便:新增配置项不影响现有结构
- 类型安全:编译时检查配置项的正确性
总结
建造者模式如同一位经验丰富的建筑师,将复杂对象的构建过程分解为清晰的步骤,最终交付一个结构完整的产品。在Spring生态中,从URI构建到配置组装,建造者模式的身影随处可见。它完美解决了复杂对象创建过程中的灵活性与安全性的矛盾,使代码既易于使用又便于维护。掌握建造者模式,开发者能够优雅地处理各种复杂对象的创建场景,构建出更加健壮、灵活的应用程序。记住:当面对具有多个组成部分的复杂对象时,建造者模式往往是比重叠构造器或JavaBean模式更优的选择。
(对您有帮助 && 觉得我总结的还行) -> 受累点个免费的赞👍,谢谢