聶永的博客

          記錄工作/學習的點點滴滴。

          建造者模式:導向器封裝生成產品的具體步驟

          《設計模式》中定義:
          Builder模式的緣起:
              假設創建游戲中的一個房屋House設施,該房屋的構建由幾部分組成,且各個部分富于變化。如果使用最直觀的設計方法,每一個房屋部分的變化,都將導致房屋構建的重新修正.....
          動機(Motivation):
              在軟件系統中,有時候面臨一個"復雜對象"的創建工作,其通常由各個部分的子對象用一定算法構成;由于需求的變化,這個復雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合到一起的算法卻相對穩定。
              如何應對種變化呢?如何提供一種"封裝機制"來隔離出"復雜對象的各個部分"的變化,從而保持系統中的"穩定構建算法"不隨需求的改變而改變?
          意圖(Intent):
              將一個復雜對象的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。
          UML 表示如下:
          uml2
          Builder模式

          這里的Builder是一個抽象類,不是接口,為了共用一些屬性和代碼,把稍微變化的部分讓子類來實現(顯然Builder 和 ConcreteOneProduct、ConcreteTwoProduct組成了個模板模式)。

          先看建造者,一個抽象類,提供一些公用實現(Builder.java):
          /**
           * 一個抽象來來替代接口
           
           @author yongboy@gmail.com
           * @date 2010-10-26
           @version 1.0
           */
          public abstract class Builder {
            protected Product product = null;

            public Builder() {
              product = new Product();
            }

            /**
             * 產生描述內容
             */
            public abstract void genDesc(String desc);

            /**
             * 繪制三角形
             */
            public abstract void genTriangle(int len);

            /**
             * 輸出最終產生的產品
             
             @return
             */
            public Product getProduct() {
              return product;
            }
          }

          一個實現,主要是繪制三角形:
          public class ConcreteOneBuilder extends Builder {

            @Override
            public void genDesc(String desc) {
              product.setDesc(desc);
            }

            @Override
            public void genTriangle(int len) {
              StringBuilder sb = new StringBuilder();
              for (int i = 1; i < len; i++) {
                for (int j = 0; j < i; j++) {
                  sb.append(" *");
                }
                sb.append("\n");
              }

              product.setContent(sb.toString());
            }
          }

          第二個實現:
          public class ConcreteTwoBuilder extends Builder {

            @Override
            public void genDesc(String desc) {
              product.setDesc(desc);
            }

            @Override
            public void genTriangle(int len) {
              StringBuilder sb = new StringBuilder();

              for (int i = len; i > 0; i--) {
                int spaceNum = len - i;

                for (int j = 0; j < spaceNum; j++) {
                  sb.append("  ");
                }
                for (int j = 0; j < i; j++) {
                  sb.append(" *");
                }

                sb.append("\n");
              }

              product.setContent(sb.toString());
            }
          }

          產品定義:
          /**
           * 一個有關三角的產品
           
           @author yongboy@gmail.com
           * @date 2010-10-26
           @version 1.0
           */
          public class Product implements Serializable {
            private final static long serialVersionUID = 23536326475869L;

            /**
             * 當前產品的描述
             */
            private String desc;

            /**
             * 當前產品的詳細內容
             */
            private String content;

            public Product() {
            }

            public String getDesc() {
              return desc;
            }

            public void setDesc(String desc) {
              this.desc = desc;
            }

            public String getContent() {
              return content;
            }

            public void setContent(String content) {
              this.content = content;
            }

            public String toString() {
              return desc + "\n" + content;
            }
          }

          導向器,封裝著產品生成的具體過程:
          /**
           * 導向器,封裝產品生生成過程
           
           @author yongboy@gmail.com
           * @date 2010-10-26
           @version 1.0
           */
          public class Director {
            private Builder builder;
            private int MAX = 25;
            private int MIN = 10;

            public Director(Builder builder) {
              this.builder = builder;
            }

            public void construct() {
              int len = getNext();
              builder.genDesc("產品型號(" + getFormatNum(len"):");
              builder.genTriangle(len);
            }

            private int getNext() {
              return getRandomNum(MIN, MAX);
            }

            private static String getFormatNum(int num) {
              return String.format("0.%d", num);
            }
            
            /**
             * 產生兩個數之間的隨機數
             
             @param min
             @param max
             @return
             */
            private int getRandomNum(double min, double max) {
              return (intmin + (int) (Math.random() (max - min));
            }
          }

          客戶端代碼調用方式:
          public class Client {
            public static void main(String[] args) {
              Builder builder = new ConcreteOneBuilder();

              Director director = new Director(builder);

              director.construct();

              Product product = builder.getProduct();

              System.out.println(product);

              System.out.println();
              System.out.println("現在輸出第二個產品:\n");
              System.out.println();

              builder = new ConcreteTwoBuilder();

              director = new Director(builder);

              director.construct();

              product = builder.getProduct();

              System.out.println(product);
            }
          }

          輸入如下:

          產品型號(0.23):
          *
          * *
          * * *
          * * * *
          * * * * *
          * * * * * *
          * * * * * * *
          * * * * * * * *
          * * * * * * * * *
          * * * * * * * * * *
          * * * * * * * * * * *
          * * * * * * * * * * * *
          * * * * * * * * * * * * *
          * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * * * * * * * *


          現在輸出第二個產品:


          產品型號(0.17):
          * * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * *
          * * * * * * * * * * * * *
          * * * * * * * * * * * *
          * * * * * * * * * * *
          * * * * * * * * * *
          * * * * * * * * *
          * * * * * * * *
          * * * * * * *
          * * * * * *
          * * * * *
          * * * *
          * * *
          * *
          *

          每一次運行可能生成變形長度都會變好,這個變好有導向器進行控制著。

          源文件下載

          posted on 2010-10-26 17:36 nieyong 閱讀(355) 評論(0)  編輯  收藏 所屬分類: Java

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2010年10月>
          262728293012
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 海林市| 莱阳市| 平武县| 陵川县| 玉林市| 瓦房店市| 衡南县| 交口县| 临江市| 垦利县| 绵阳市| 福清市| 长丰县| 大洼县| 镇赉县| 景泰县| 正宁县| 建始县| 莱州市| 扎兰屯市| 鄂尔多斯市| 尉氏县| 泽州县| 嘉鱼县| 日照市| 忻州市| 马山县| 迁安市| 沅江市| 固阳县| 三明市| 文山县| 托克逊县| 东海县| 鹤峰县| 班戈县| 顺平县| 河津市| 牡丹江市| 罗源县| 泗洪县|