1. 什么是建造者模式
建造者模式 (Builder Pattern),也被称为生成器模式,是一种创建型设计模式。
- 定义:将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式要解决的问题:
- 建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无需知道其内部的具体构造细节。
2. 建造者模式的结构
建造者(Builder)模式包含以下4个角色:
- 抽象建造者类(Builder):规定要实现复杂对象的哪些部分的创建,并不涉及具体的部件对象的创建。
- 具体建造者类(ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供一个方法,返回创建好的复杂产品对象。
- 产品类(Product):要创建的复杂对象 (包含多个组成部件)。
- 指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指挥者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建(客户端一般只需要与指挥者进行交互)。
3. 代码示例
下面是一个SQL查询生成器的例子,展示如何使用建造者模式生成不同数据库的SQL查询语句。
产品类
public class SqlQuery {
private String select;
private String from;
private String where;
private String groupBy;
private String orderBy;
private String limit;
public SqlQuery(String select, String from) {
this.select = select;
this.from = from;
}
// Getters and setters
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("SELECT ").append(select).append(" FROM ").append(from);
if (where != null && !where.isEmpty()) {
sb.append(" WHERE ").append(where);
}
if (groupBy != null && !groupBy.isEmpty()) {
sb.append(" GROUP BY ").append(groupBy);
}
if (orderBy != null && !orderBy.isEmpty()) {
sb.append(" ORDER BY ").append(orderBy);
}
if (limit != null && !limit.isEmpty()) {
sb.append(" LIMIT ").append(limit);
}
return sb.toString();
}
}
抽象建造者
public abstract class SqlQueryBuilder {
protected SqlQuery sqlQuery;
public void createSqlQuery(String select, String from) {
sqlQuery = new SqlQuery(select, from);
}
public SqlQuery getSqlQuery() {
return sqlQuery;
}
public abstract void buildWhere();
public abstract void buildGroupBy();
public abstract void buildOrderBy();
public abstract void buildLimit();
}
具体建造者
public class MySqlQueryBuilder extends SqlQueryBuilder {
@Override
public void buildWhere() {
sqlQuery.setWhere("1 = 1"); // MySQL不需要限制行数
}
@Override
public void buildGroupBy() {
sqlQuery.setGroupBy("deptno, ename, hiredate");
}
@Override
public void buildOrderBy() {
sqlQuery.setOrderBy("hiredate DESC");
}
@Override
public void buildLimit() {
sqlQuery.setLimit("0, 10"); // MySQL分页从0开始
}
}
public class OracleQueryBuilder extends SqlQueryBuilder {
@Override
public void buildWhere() {
sqlQuery.setWhere("rownum <= 1000"); // Oracle查询最多返回1000行数据
}
@Override
public void buildGroupBy() {
sqlQuery.setGroupBy("deptno, ename, hiredate");
sqlQuery.setSelect(sqlQuery.getSelect() + ", deptno, ename, hiredate");
}
@Override
public void buildOrderBy() {
sqlQuery.setOrderBy("hiredate");
}
@Override
public void buildLimit() {
sqlQuery.setLimit("10");
}
}
指挥者类
public class SqlQueryDirector {
private SqlQueryBuilder sqlQueryBuilder;
public void setSqlQueryBuilder(SqlQueryBuilder sqlQueryBuilder) {
this.sqlQueryBuilder = sqlQueryBuilder;
}
public void buildSqlQuery(String select, String from) {
sqlQueryBuilder.createSqlQuery(select, from);
sqlQueryBuilder.buildWhere();
sqlQueryBuilder.buildGroupBy();
sqlQueryBuilder.buildOrderBy();
sqlQueryBuilder.buildLimit();
}
}
客户端
public class Client {
public static void main(String[] args) {
// 创建MySQL建造者
SqlQueryBuilder mySqlQueryBuilder = new MySqlQueryBuilder();
// 创建Oracle建造者
SqlQueryBuilder oracleQueryBuilder = new OracleQueryBuilder();
// 指导者
SqlQueryDirector sqlQueryDirector = new SqlQueryDirector();
// 构建MySQL查询语句
sqlQueryDirector.setSqlQueryBuilder(mySqlQueryBuilder);
sqlQueryDirector.buildSqlQuery("*", "table1");
SqlQuery mySqlQuery = mySqlQueryBuilder.getSqlQuery();
System.out.println("MySQL Query: " + mySqlQuery);
// 构建Oracle查询语句
sqlQueryDirector.setSqlQueryBuilder(oracleQueryBuilder);
sqlQueryDirector.buildSqlQuery("*", "table2");
SqlQuery oracleQuery = oracleQueryBuilder.getSqlQuery();
System.out.println("Oracle Query: " + oracleQuery);
}
}
4. 建造者模式在实际开发中的应用
建造者模式在实际开发中的应用主要体现在以下几个方面:
- 复杂对象的创建:例如,在创建一个复杂对象时,如果这个对象有很多可选参数,使用建造者模式可以避免构造函数参数列表过长的问题。
- 多步骤创建过程:例如,在构建SQL查询、创建报告等需要多个步骤的过程中,使用建造者模式可以将这些步骤分离出来,使得代码更易于维护和扩展。
- 对象的不变性:例如,创建一个不可变对象时,可以使用建造者模式来确保对象在创建后不被修改。
5. 建造者模式与工厂模式的区别
-
工厂模式:
- 用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。
- 主要关注的是创建单个对象。
-
建造者模式:
- 用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。
- 主要关注的是如何一步一步创建一个复杂的对象。
- 更强调创建过程的分步和顺序。
总之,建造者模式可以很好地解决创建复杂对象时的代码复用性和可维护性问题,而工厂模式则更加适用于创建一组相关的对象。