天天看點

跟屌絲大哥學習設計模式--生成器模式(Builder)

builder 模式的重心在于分離建構算法和具體的構造實作,進而使建構算法可以重用。

builder 模式的構成分為兩部分:一部分是builder接口,定義了如何建構各個部件,并裝配到産品中去;另一部分是director,定義如何來建構産品,director 負責整體的建構算法,而且通常是分步來執行的。

注:這裡的建構算法是指:通過什麼樣的方式來組裝産品;建構産品指的是:建構一個複雜對象。

builder 模式就是将建構産品部件群組裝産品的過程分開,即實作了産品部件群組裝産品過程的解耦,可以使得組裝産品過程得到複用

跟屌絲大哥學習設計模式--生成器模式(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");

           }

          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 {

  @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");

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

       }

                    concretebuilder builder = new concretebuilder("001", 82345l, 67890l);

                    insurancecontract contract = builder.setpersonname("張三").setotherdata("test").build();

                    contract.someoperation();

====================================分割線================================

最新内容請見作者的github頁:http://qaseven.github.io/

繼續閱讀