qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

跟屌丝大哥学习设计模式--生成器模式(Builder)

Builder 模式的重心在于分离构建算法和具体的构造实现,从而使构建算法可以重用。

Builder 模式的构成分为两部分:一部分是Builder接口,定义了如何构建各个部件,并装配到产品中去;另一部分是Director,定义如何来构建产品,Director 负责整体的构建算法,而且通常是分步来执行的。

注:这里的构建算法是指:通过什么样的方式来组装产品;构建产品指的是:构建一个复杂对象。

Builder 模式就是将构建产品部件组装产品的过程分开,即实现了产品部件组装产品过程的解耦,可以使得组装产品过程得到复用



public class ExportHeaderModel {

         private String depId;
         private String exportDate;
         省略getter 和 setter
 } 

public class ExportDataModel {

       private String productId;
       private double price;
       private double amount;
       省略getter 和 setter
}

public class ExportFooterModel {

      private String exportUser;

      省略getter 和 setter

 }
/**
 * 生成器接口,定义一个输出文件对象所需的各个部件的操作
 *
 */
public interface Builder {

          /**
           * 构建输出文件的Header部分
           * @param ehm 文件头的内容
           */
         public void buildHeader(ExportHeaderModel ehm);
         /**
          * 构建输出文件的Body部分
          * @param mapData 要输出文件的数据内容
          */
        public void buildBody(Map<String, Collection<ExportDataModel>> mapData);
        /**
         * 构建要输出文件的Footer部分
         * @param efm 文件尾的内容
         */
        public void buildFooter(ExportFooterModel efm);
}

/**
 * 实现导出数据到文本文件的生成器
 *
 */

public class TxtBuilder implements Builder {

          /**
           * 用来记录构建文件的内容,相当于产品
           */
          private StringBuffer buffer = new StringBuffer();
 
          @Override
          public void buildHeader(ExportHeaderModel ehm) {
                    buffer.append(ehm.getDepId() + "," + ehm.getExportDate() + "\n");
           }

          @Override
          public void buildBody(Map<String, Collection<ExportDataModel>> mapData) {
                   for(String tblName : mapData.keySet()){
                           buffer.append(tblName + "\n");
                           for(ExportDataModel edm : mapData.get(tblName)){
                                    buffer.append(edm.getProductId() + "," + edm.getPrice() + "," + edm.getAmount() + "\n");
                            }
                   }
         }

   @Override
         public void buildFooter(ExportFooterModel efm) {
                    buffer.append(efm.getExportUser());
         }

         public StringBuffer getResult(){
                   return buffer;
         }
}

public class XmlBuilder implements Builder {

          private StringBuffer buffer = new StringBuffer();
 

  @Override
          public void buildHeader(ExportHeaderModel ehm) {
                    buffer.append("<?xml version='1.0' encoding='gb2312' ?>\n");
                    buffer.append("<Report>\n");
                    buffer.append("  <Header>\n");
                    buffer.append("    <DepId>" + ehm.getDepId() + "</DepId>\n");
                    buffer.append("    <ExportDate>" + ehm.getExportDate() + "</ExportDate>\n");
                    buffer.append("  </Header>\n");
         }
     @Override
         public void buildBody(Map<String, Collection<ExportDataModel>> mapData) {
                  buffer.append("  <Body>\n");
                  for(String tblName : mapData.keySet()){
                          buffer.append("    <Datas TableName=\"" + tblName + "\">\n");
                          for(ExportDataModel edm : mapData.get(tblName)){
                                     buffer.append("      <Data>\n");
                                     buffer.append("        <ProductId>" + edm.getProductId() + "</ProductId>\n");
                                     buffer.append("        <Price>" + edm.getPrice() + "</Price>\n");
                                     buffer.append("        <Amount>" + edm.getAmount() + "</Amount>\n");
                                     buffer.append("      </Data>\n");
                          }
                         buffer.append("    </Datas>\n");
                }
                buffer.append("  </Body>\n");
        }

      @Override
         public void buildFooter(ExportFooterModel efm) {
                   buffer.append("  <Footer>\n");
                   buffer.append("    <ExportUser>" + efm.getExportUser() + "</ExportUser>\n");
                   buffer.append("  </Footer>\n");
                   buffer.append("</Report>\n");
         }

         public StringBuffer getResult(){
                  return buffer;
         }
}

/**
 * 指导者,指导使用生成器的接口来构建输出的文件对象
 *

/**
 * 指导者,指导使用生成器的接口来构建输出的文件对象
 *
 */
public class Director {

          /**
           * 持有当前需要使用的生成器对象
           */
         private Builder builder;
 
         public Director(Builder builder){
                   this.builder = builder;
         }
         /**
          * 指导生成器构建最终的输出文件的对象
          * @param ehm 文件头的内容
          * @param mapData 数据的内容
          * @param efm 文件尾的内容
          */
        public void construct(ExportHeaderModel ehm, Map<String, Collection<ExportDataModel>> mapData,
                ExportFooterModel efm){
                     //构建Header
                     builder.buildHeader(ehm);
                     //构建Body
                     builder.buildBody(mapData);
                    //构建Footer
                     builder.buildFooter(efm);
        }
}

public class Client {

          public static void main(String[] args) {
                  ExportHeaderModel ehm = new ExportHeaderModel();
                  ehm.setDepId("一分公司");
                  ehm.setExportDate("2011-06-12");
  
                  Map<String, Collection<ExportDataModel>> mapData = new HashMap<String, Collection<ExportDataModel>>();
                  Collection<ExportDataModel> coll = new ArrayList<ExportDataModel>();
  
                  ExportDataModel edml = new ExportDataModel();
                  edml.setAmount(80);
                  edml.setProductId("产品001号");
                  edml.setPrice(100);
                  coll.add(edml);
  
                 ExportDataModel edm2 = new ExportDataModel();
                 edm2.setAmount(60);
                 edm2.setProductId("产品002号");
                 edm2.setPrice(120);
                 coll.add(edm2);
  
                mapData.put("销售记录表", coll);
  
                ExportFooterModel efm = new ExportFooterModel();
                efm.setExportUser("张三");
  
                TxtBuilder txtBuilder = new TxtBuilder();
                Director director = new Director(txtBuilder);
                director.construct(ehm, mapData, efm);
                System.out.println("输出到文本文件的内容:\n" + txtBuilder.getResult());
  
                XmlBuilder xmlBuilder = new XmlBuilder();
               Director director2 = new Director(xmlBuilder);
               director2.construct(ehm, mapData, efm);
               System.out.println("输出到Xml文件的内容:\n" + xmlBuilder.getResult());
        }

}

● 使用生成器模式创建复杂对象:

① 由于使用Builder 模式来创建某个对象,因此就没有必要再定义一个Builder接口,直接提供一个具体的构建器类就可以了。

② 对于创建一个复杂的对象,可能会有很多种不同的选择和步骤,干脆去掉“Director”,把Director的功能和Client 的功能合并起来,也就是说这个时候,Client 相当于指导者,它来指导构建器类去构建需要的复杂对象。

public class ConcreteBuilder {

        private String contractId;
        private String personName;
        private String companyName;
        private long beginDate;
        private long endDate;
        private String otherData;
 
       /**
         * 构造方法 传入必填数据
         * @param contractId 保险合同号
         * @param beginDate 保险开始生效的日期
         * @param endDate 保险失效的日期
         */
       public ConcreteBuilder(String contractId, long beginDate, long endDate){
                this.contractId = contractId;
                this.beginDate = beginDate;
                this.endDate = endDate;
        }
        /**
          * 选填数据,被保险人
          * @param personName 被保险人名
          * @return 构建对象
          */
        public ConcreteBuilder setPersonName(String personName){
                  this.personName = personName;
                  return this;
        }
        /**
         * 选填数据,被保险公司
         * @param companyName 被保险公司名
         * @return 构建对象
         */
       public ConcreteBuilder setCompanyName(String companyName){
                 this.companyName = companyName;
                 return this;
        }
        /**
         * 选填数据,其它数据
         * @param otherData 其它数据
         * @return 构建对象
         */
        public ConcreteBuilder setOtherData(String otherData){
                this.otherData = otherData;
                return this;
        }
 
        public InsuranceContract build(){
               if(contractId == null || contractId.trim().length() == 0){
                        throw new IllegalArgumentException("合同编号不能空!");
                }
  
                boolean signPerson = (personName != null && personName.trim().length() > 0);
                boolean signCompany = (companyName != null && companyName.trim().length() > 0);
  
                if(!(signPerson ^ signCompany)){
                            throw new IllegalArgumentException("一份保险不能没有签订对象,且不能同时与人和公司签订!");
                }
  
               if(beginDate <= 0){
                         throw new IllegalArgumentException("合同必须有保险开始生效的日期!");
                }
  
               if(endDate <= 0){
                        throw new IllegalArgumentException("合同必须有保险失效的日期!");
               }
  
               if(endDate <= beginDate){
                        throw new IllegalArgumentException("保险失效日期必须大于生效日期!");
               }
  
                return new InsuranceContract(this);
         }
 
          public String getContractId() {
                    return contractId;
          }
          public String getPersonName() {
                    return personName;
          }
          public String getCompanyName() {
                    return companyName;
          }
          public long getBeginDate() {
                     return beginDate;
          }
          public long getEndDate() {
                    return endDate;
          }
          public String getOtherData() {
                    return otherData;
          }
}

/**
 * 保险合同对象
 * @author joe
 *
 */
public class InsuranceContract {

        /**
         * 保险合同编号
         */
       private String constractId;
       /**
        * 被保险的人
        */
       private String personName;
       /**
        * 被保险的公司
        */
      private String companyName;
      /**
       * 保险开始生效的日期
      */
      private long beginDate;
      /**
       * 保险失效的日期
       */
      private long endDate;
      /**
       * 其它数据
       */
      private String otherData;
      /**
       * 构造方法,访问级别是同包能访问
       * @param builder
       */
      InsuranceContract(ConcreteBuilder builder){
             this.constractId = builder.getContractId();
             this.personName = builder.getPersonName();
             this.companyName = builder.getCompanyName();
             this.beginDate = builder.getBeginDate();
             this.endDate = builder.getEndDate();
             this.otherData = builder.getOtherData();
       }
 
      public void someOperation(){
              System.out.println("Now in Insurance Contract someOperation == " + this.constractId);
       }

}

public class Client {

          public static void main(String[] args) {
                    ConcreteBuilder builder = new ConcreteBuilder("001", 82345L, 67890L);
                    InsuranceContract contract = builder.setPersonName("张三").setOtherData("test").build();
                    contract.someOperation();
          }
}

posted on 2012-12-17 19:33 顺其自然EVO 阅读(191) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2012年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜