建造器模式

1. 使用场景

当一个对象的构建过程不固定,需要根据各种条件生成最后对象时

2. 体现举例

字符串处理

在多条件SQL组合查询中经常可见建造器的身影:

public static String buildSQL(String name, Integer age, Date birthday) { StringBuilder sb = new StringBuilder(256); sb.append("select * from t_user where 1=1"); if (name != null && !name.equals("")) { sb.append(" and name=?"); } if (age != null) { sb.append(" and age=?"); } if (birthday != null) { sb.append(" and birthday=?"); } return sb.toString(); } public static void main(String[] args) { System.out.println(buildSQL("张三", null, null)); // 输出: select * from t_user where 1=1 and name=? System.out.println(buildSQL(null, 18, null)); // 输出: select * from t_user where 1=1 and age=? System.out.println(buildSQL("张三", 18, null)); // 输出: select * from t_user where 1=1 and name=? and age=? System.out.println(buildSQL("张三", 18, new Date())); // 输出: select * from t_user where 1=1 and name=? and age=? and birthday=? }

要点

其中StringBuilder 实现了建造器模式:StringBuilder根据各个条件是否存在构建最后的String对象

日期处理

import java.time.LocalDate; import java.time.format.DateTimeFormatterBuilder; import java.time.format.TextStyle; import java.time.temporal.ChronoField; import java.util.Locale; public class Test5 { public static void main(String[] args) { LocalDate date = LocalDate.of(2017, 2, 19); System.out.println(date.format(new DateTimeFormatterBuilder() .appendValue(ChronoField.YEAR_OF_ERA) .appendLiteral("年") .appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendLiteral("月") .appendValue(ChronoField.DAY_OF_MONTH) .appendLiteral("日") .toFormatter(Locale.CHINA))); // 输出: 2017年02月19日 System.out.println(date.format(new DateTimeFormatterBuilder() .appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL) .appendLiteral(" ") .appendValue(ChronoField.DAY_OF_MONTH) .appendLiteral(", ") .appendValue(ChronoField.YEAR_OF_ERA) .toFormatter(Locale.ENGLISH))); // 输出: February 19, 2017 } }

要点

其中 DateTimeFormatterBuilder 实现了建造器模式,因为日期的格式多种多样,构造 DateTimeFormatter对象 需要非常灵活,所以DateTimeFormatterBuilder 提供了一系列append方法来完成各种格式控制,最后toFormatter方法生成 DateTimeFormatter对象

构建Query对象

在Hibernate查询时,会用到Query对象,类似的,Query对象需要的HQL语句多种多样,并且每条HQL语句需要设置的参数,是否需要分页都不确定。因此Hibernate也是采用了建造器模式来创建Query对象:

import java.util.List; import org.hibernate.Query; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; @Repository public class UserDao { @Autowired private SessionFactory sf; public List<User> findByName(String name){ Query q = sf.getCurrentSession() .createQuery("from User where name = ?") .setString(0, name); return q.list(); } public List<User> findByNameAndAge(String name, int age){ Query q = sf.getCurrentSession() .createQuery("from User where name = ? and age = ?") .setString(0, name) .setInteger(1, age); return q.list(); } public List<User> findByPage(int page, int size){ Query q = sf.getCurrentSession() .createQuery("from User") .setFirstResult((page-1)*size) .setMaxResults(size); return q.list(); } }

要点

其中 createQuery() , setXXX() 等方法均体现了建造器模式,通过设置不同的条件来创建最终的Query对象。

与前面两个例子不同之处在于,没有抽取独立的Builder类


results matching ""

    No results matching ""