【15】创建型-Builder模式

こ雲淡風輕ζ 提交于 2020-03-01 14:18:40

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());
    }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!