java设计模式-创建型模式-建造者模式
场景举例
根据表名、每页条数、偏移量等属性进行拼接组装,并且根据不同的数据库类型生成不同的sql脚本
观察Lombok @Builder注解生成的代码
源码
package xin.yangshuai.basic01.gof23.builder;import lombok.Builder;@Builder
public class DatabaseSqlLombok {/*** 数据库类型*/private String database;/*** 表名*/private String tableName;/*** 每页条数*/private Integer pageSize;/*** 偏移量*/private Integer offset;/*** sql*/private String sql;
}
编译后的代码(反编译回java代码)
package xin.yangshuai.basic01.gof23.builder;public class DatabaseSqlLombok {private String database;private String tableName;private Integer pageSize;private Integer offset;private String sql;DatabaseSqlLombok(String database, String tableName, Integer pageSize, Integer offset, String sql) {this.database = database;this.tableName = tableName;this.pageSize = pageSize;this.offset = offset;this.sql = sql;}public static DatabaseSqlLombokBuilder builder() {return new DatabaseSqlLombokBuilder();}public static class DatabaseSqlLombokBuilder {private String database;private String tableName;private Integer pageSize;private Integer offset;private String sql;DatabaseSqlLombokBuilder() {}public DatabaseSqlLombokBuilder database(String database) {this.database = database;return this;}public DatabaseSqlLombokBuilder tableName(String tableName) {this.tableName = tableName;return this;}public DatabaseSqlLombokBuilder pageSize(Integer pageSize) {this.pageSize = pageSize;return this;}public DatabaseSqlLombokBuilder offset(Integer offset) {this.offset = offset;return this;}public DatabaseSqlLombokBuilder sql(String sql) {this.sql = sql;return this;}public DatabaseSqlLombok build() {return new DatabaseSqlLombok(this.database, this.tableName, this.pageSize, this.offset, this.sql);}public String toString() {return "DatabaseSqlLombok.DatabaseSqlLombokBuilder(database=" + this.database + ", tableName=" + this.tableName + ", pageSize=" + this.pageSize + ", offset=" + this.offset + ", sql=" + this.sql + ")";}}
}
建造者模式中的几种角色
产品(Product)
具体的产品
抽象建造者(Builder)
定义创建产品各个部件的方法,通常包括多个创建产品部件的方法和一个返回具体产品的方法
具体建造者(ConcreteBuilder)
实现抽象建造者的接口
指挥者(Director)
控制建造者创建产品各个部件的顺序
代码示例
参考lombok生成的代码,定义建造者模式中的各个角色
产品:DatabaseSql
package xin.yangshuai.basic01.gof23.builder;public class DatabaseSql {/*** 数据库类型*/private String database;/*** 表名*/private String tableName;/*** 每页条数*/private Integer pageSize;/*** 偏移量*/private Integer offset;/*** sql*/private String sql;public DatabaseSql() {}public DatabaseSql(String database, String tableName, Integer pageSize, Integer offset, String sql) {this.database = database;this.tableName = tableName;this.pageSize = pageSize;this.offset = offset;this.sql = sql;}public String getDatabase() {return database;}public void setDatabase(String database) {this.database = database;}public String getTableName() {return tableName;}public void setTableName(String tableName) {this.tableName = tableName;}public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getOffset() {return offset;}public void setOffset(Integer offset) {this.offset = offset;}public String getSql() {return sql;}public void setSql(String sql) {this.sql = sql;}
}
抽象建造者:DatabaseSqlBuilder
package xin.yangshuai.basic01.gof23.builder;public interface DatabaseSqlBuilder {/*** 数据库类型** @return*/DatabaseSqlBuilder database();/*** 表名** @param tableName* @return*/DatabaseSqlBuilder tableName(String tableName);/*** 每页条数** @param pageSize* @return*/DatabaseSqlBuilder pageSize(Integer pageSize);/*** 偏移量** @param offset* @return*/DatabaseSqlBuilder offset(Integer offset);/*** sql** @return*/DatabaseSqlBuilder sql();/*** 生成DatabaseSql** @return*/DatabaseSql build();
}
具体建造者:MySQLDatabaseSqlBuilder
package xin.yangshuai.basic01.gof23.builder;public class MySQLDatabaseSqlBuilder implements DatabaseSqlBuilder {/*** 数据库类型*/private String database;/*** 表名*/private String tableName;/*** 每页条数*/private Integer pageSize;/*** 偏移量*/private Integer offset;/*** sql*/private String sql;@Overridepublic DatabaseSqlBuilder database() {this.database = "MySQL";return this;}public DatabaseSqlBuilder tableName(String tableName) {this.tableName = tableName;return this;}public DatabaseSqlBuilder pageSize(Integer pageSize) {this.pageSize = pageSize;return this;}public DatabaseSqlBuilder offset(Integer offset) {this.offset = offset;return this;}@Overridepublic DatabaseSqlBuilder sql() {this.sql = "select * from " + tableName + " limit " + offset + "," + pageSize + ";";return this;}@Overridepublic DatabaseSql build() {return new DatabaseSql(database, tableName, pageSize, offset, sql);}
}
指挥者:DatabaseSqlDirector
package xin.yangshuai.basic01.gof23.builder;public class DatabaseSqlDirector {private DatabaseSqlBuilder databaseSqlBuilder;public void setDatabaseSqlBuilder(DatabaseSqlBuilder databaseSqlBuilder) {this.databaseSqlBuilder = databaseSqlBuilder;}public DatabaseSql build(){if (databaseSqlBuilder != null) {return databaseSqlBuilder.database().sql().build();}return null;}
}
方法调用测试
package xin.yangshuai.basic01.gof23.builder;public class Main {public static void main(String[] args) {DatabaseSqlBuilder databaseSqlBuilder = new MySQLDatabaseSqlBuilder().tableName("test_user").offset(0).pageSize(10);DatabaseSqlDirector databaseSqlDirector = new DatabaseSqlDirector();databaseSqlDirector.setDatabaseSqlBuilder(databaseSqlBuilder);DatabaseSql databaseSql = databaseSqlDirector.build();System.out.println(databaseSql.getDatabase());System.out.println(databaseSql.getSql());}
}
响应信息
MySQL
select * from test_user limit 0,10;
个人理解
- 指挥者的作用:设置比较复杂的属性,比如上面例子中设置sql属性(需要其它属性进行组合,拼接),可能需要指挥者类来控制执行的顺序
- 一般情况应该不需要指挥者类
如有不对,欢迎指正!