1、上下文及定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.用户不知道内部的具体构建细节.Builder模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用中才能体会到。
2、常用场景
是为了将构建复杂对象的过程和它的部件解耦.注意: 是解耦过程和部件。
因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮 方向盘 发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder模式就是为了将部件和组装过程分开。
在Java实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池。
"池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能.修改Builder模式中Director类使之能诊断"断肢"断在哪个部件上,再修复这个部件。
3、解决方法
首先假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部件的创建分别开来,分别用Builder类和Director类来表示。
4、抽象模型
5、代码实例
(1)模型实例
builder接口
public interface Builder {
//创建部件A 比如创建汽车车轮
void buildPartA();
//创建部件B 比如创建汽车方向盘
void buildPartB();
//创建部件C 比如创建汽车发动机
void buildPartC();
//返回最后组装成品结果 (返回最后装配好的汽车)
//成品的组装过程不在这里进行,而是转移到下面的Director类中进行.
//从而实现了解耦过程和部件
Product getResult();
}
director
public class Director {
private Builder builder;
public Director( Builder builder ) {
this.builder = builder;
}
// 将部件partA partB partC最后组成复杂对象
//这里是将车轮 方向盘和发动机组装成汽车的过程
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
builder实现
public class ConcreteBuilder implements Builder {
Part partA, partB, partC;
public void buildPartA() {
//这里是具体如何构建partA的代码
};
public void buildPartB() {
//这里是具体如何构建partB的代码
};
public void buildPartC() {
//这里是具体如何构建partB的代码
};
public Product getResult() {
//返回最后组装成品结果
};
}
客户端
ConcreteBuilder builder = new ConcreteBuilder();
Director director = new Director( builder );
director.construct();
Product product = builder.getResult();
(2)Criteria实例
criteria的director
/**
* @author caibosi
* @created 2014-06-03
*/
public class SimpleCriteria<T> {
protected List<Criterion> criteria;
protected Page page;
protected Class<T> cls;
public static SimpleCriteria forClass(Class clz){
return new SimpleCriteria();
}
public SimpleCriteria add(Criterion criterion){
criteria.add(criterion);
return this;
}
public SimpleCriteria() {
criteria = new ArrayList<Criterion>();
this.cls = (Class<T>) DAOTool.getTypeArguments(SimpleCriteria.class, this.getClass()).get(0);
}
public String toSql(){
StringBuilder strBuilder = new StringBuilder();
int size = criteria.size();
for(int i=0;i<size;i++){
Criterion criterion = criteria.get(i);
if(StringTool.isEmpty(criterion.getOp()) && size > 1 && i != 0){
strBuilder.append(" and ");
}
strBuilder.append(criterion.toSql());
}
return strBuilder.toString();
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
public Class<T> getCls() {
return cls;
}
public void setCls(Class<T> cls) {
this.cls = cls;
}
}
where builder
/**
*
* <sql id="Example_Where_Clause" >
<where >
<foreach collection="oredCriteria" item="criteria" separator="or" >
<if test="criteria.valid" >
<trim prefix="(" suffix=")" prefixOverrides="and" >
<foreach collection="criteria.criteria" item="criterion" >
<choose >
<when test="criterion.noValue" >
and ${criterion.condition}
</when>
<when test="criterion.singleValue" >
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue" >
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue" >
and ${criterion.condition}
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
* @author caibosi
* @created 2014-06-03
*/
public class Criterion {
private Criterion leftCriterion;
private Criterion rightCriterion;
private String op;
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
public Criterion(Criterion left,Criterion right,String op){
this.leftCriterion = left;
this.rightCriterion = right;
this.op = op;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
public Criterion getLeftCriterion() {
return leftCriterion;
}
public void setLeftCriterion(Criterion leftCriterion) {
this.leftCriterion = leftCriterion;
}
public Criterion getRightCriterion() {
return rightCriterion;
}
public void setRightCriterion(Criterion rightCriterion) {
this.rightCriterion = rightCriterion;
}
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
public String toSql(){
StringBuilder strBuilder = new StringBuilder();
if(StringTool.isEmpty(op)){
strBuilder.append(" ");
strBuilder.append(toSimpleSql());
strBuilder.append(" ");
}else if("or".equals(op)){
strBuilder.append("( ");
strBuilder.append(leftCriterion.toSql());
strBuilder.append(" or ");
strBuilder.append(rightCriterion.toSql());
strBuilder.append(" ) ");
}else if("and".equals(op)){
strBuilder.append("( ");
strBuilder.append(leftCriterion.toSql());
strBuilder.append(" and ");
strBuilder.append(rightCriterion.toSql());
strBuilder.append(" ) ");
}
return strBuilder.toString();
}
private String toSimpleSql(){
StringBuilder strBuilder = new StringBuilder();
/**
* <when test="criterion.noValue" >
and ${criterion.condition}
</when>
*/
if(noValue == true){
strBuilder.append(condition);
return strBuilder.toString();
}
/**
* <when test="criterion.singleValue" >
and ${criterion.condition} #{criterion.value}
</when>
*/
if(singleValue == true){
strBuilder.append(condition);
strBuilder.append(" ");
strBuilder.append(value);
return strBuilder.toString();
}
/**
* <when test="criterion.betweenValue" >
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
*/
if(betweenValue == true){
strBuilder.append(condition);
strBuilder.append(" ");
strBuilder.append("'");
strBuilder.append(value);
strBuilder.append("'");
strBuilder.append(" and ");
strBuilder.append("'");
strBuilder.append(secondValue);
strBuilder.append("'");
return strBuilder.toString();
}
/**
* <when test="criterion.listValue" >
and ${criterion.condition}
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
#{listItem}
</foreach>
</when>
*/
if(listValue == true){
strBuilder.append(condition);
Collection items = (Collection) value;
strBuilder.append("(");
strBuilder.append(StringTool.join(items,','));
strBuilder.append(")");
return strBuilder.toString();
}
return " ";
}
}
and or builder
/**
* @author caibosi
* @created 2014-06-09
*/
public class Restrictions {
//and or restrictions
public static Criterion and(Criterion left,Criterion right){
return new Criterion(left,right,"and");
}
public static Criterion or(Criterion left,Criterion right){
return new Criterion(left,right,"or");
}
//common restrictions
public static Criterion isNull(String property) {
return new Criterion(StringTool.camelhumpToUnderline(property) + " is null");
}
public static Criterion isNotNull(String property) {
return new Criterion(StringTool.camelhumpToUnderline(property) + " is not null");
}
public static Criterion equalTo(String property,Object value) {
return new Criterion(StringTool.camelhumpToUnderline(property) + " =", value, property);
}
public static Criterion NotEqualTo(String property,Object value) {
return new Criterion(StringTool.camelhumpToUnderline(property) + " <>", value, property);
}
public static Criterion greaterThan(String property,Object value) {
return new Criterion(StringTool.camelhumpToUnderline(property) +" >", value, property);
}
public static Criterion greaterThanOrEqualTo(String property,Object value) {
return new Criterion(StringTool.camelhumpToUnderline(property)+" >=", value, property);
}
public static Criterion lessThan(String property,Object value) {
return new Criterion(StringTool.camelhumpToUnderline(property)+" <", value, property);
}
public static Criterion lessThanOrEqualTo(String property,Object value) {
return new Criterion(StringTool.camelhumpToUnderline(property)+" <=", value, property);
}
public static Criterion in(String property,List values) {
return new Criterion(StringTool.camelhumpToUnderline(property)+" in", values, property);
}
public static Criterion NotIn(String property,List values) {
return new Criterion(StringTool.camelhumpToUnderline(property)+" not in", values, property);
}
public static Criterion between(String property,Object value1, Object value2) {
return new Criterion(StringTool.camelhumpToUnderline(property)+" between", value1, value2, property);
}
public static Criterion notBetween(String property,Object value1, Object value2) {
return new Criterion(StringTool.camelhumpToUnderline(property)+" not between", value1, value2, property);
}
}
客户端
@Test
public void testCriteria(){
SimpleCriteria criteria = SimpleCriteria.forClass(TaskRule.class);
criteria.add(Restrictions.or(
Restrictions.and(Restrictions.greaterThan("id", 1), Restrictions.equalTo("name", "persia")),
Restrictions.between("time", "2013-06-01", "2013-05-02")));
criteria.add(Restrictions.greaterThan("num",2));
System.out.println(criteria.toSql());
SimpleCriteria criteria1 = SimpleCriteria.forClass(TaskRule.class);
criteria1.add(Restrictions.greaterThan("id",1));
System.out.println(criteria1.toSql());
}
来源:oschina
链接:https://my.oschina.net/u/1383356/blog/284644