設計模式之(五)建造者(生成器)模式(Builder)

  考慮這樣一種業務場景,咱們構建一個業務對象,可是這個業務對象及其複雜。爲了代碼的根號的可讀性,咱們會把這個對象的構建過程根據精密聯繫的程度來拆分紅幾個類來完成。最後再放到一塊兒使用來生成複雜對象。這個業務場景很是常見,接下來就分析一下解決這個問題更靈活的方式,即:建造者模式。算法

  建造者模式定義及規範代碼

  將一個複雜對象的建立與它的表示分離,使得一樣的建立過程能夠建立不一樣的表示。app

  看到這個定義之後,確定有不少讀者會有疑問,【複雜對象的建立】的建立好理解,可是【(複雜對象)的表示】是什麼意思呢,這裏爲了解決讀者可能出現猴急的心情,先大概解釋一下。首先看建造者模式的結構圖ide

            

  Builder:生成器接口,定義建立一個產品所須要的的各個部分的操做。ui

  ConcreateBuilder:具體的生成器實現,這個產品在組裝過程當中各個部分所須要的共同的操做。而且還提供一個供用戶獲取組裝完產品的對象。this

  Director:指導者,主要用來使用 builder 接口,以一個統一的過程來構建所須要的 Product 對象spa

  Product:產品,表示被生成器構建的複雜對象,包含多個部件。code

  接下來講下個人理解。建造者模式在建立類似的複雜對象使用,其中 Builder 定義建立這個複雜對象的過程,把建立過程分爲不一樣的部分,也能夠說是不一樣的組成部分。而 ConcreateBuilder 則是對複雜對象建立每部分共同的部分實現出來。xml

     類似複雜對象的每步驟類似部分在 ConcreateBuilder 建立,而不一樣部分則另外建立,以參數形式傳入相應的部分。這個具體如何組裝,則是在 Director 中來完成。在這個初步理解的基礎上。經過如下例子來具體分析。對象

  1 /**
  2  * 生成器接口,定義建立一個輸出文件對象所需的各個部件的操做
  3  * @author Administrator
  4  */
  5 public interface Builder {
  6     
  7     //構建輸出的文件頭內容
  8     public void builderHeader(ExportHeaderModel ehm);
  9     
 10     //構建輸出的文件正文數據內容
 11     public void BuilderBody(Map<String,Collection<ExportDataModel>> bodyData);
 12     
 13     //構建文件尾內容
 14     public void builderFooter(ExportFooterModel efm);
 15 }
 16 
 17 /**
 18  * 描述輸出到文件頭部內容的對象
 19  */
 20 public class ExportHeaderModel {
 21     
 22     /**
 23      * 分公司或門市店的編號
 24      */
 25     private String DepID;
 26     
 27     /**
 28      * 導出數據的日期
 29      */
 30     private String exportDate;
 31 
 32     public String getDepID() {
 33         return DepID;
 34     }
 35 
 36     public void setDepID(String depID) {
 37         DepID = depID;
 38     }
 39 
 40     public String getExportDate() {
 41         return exportDate;
 42     }
 43 
 44     public void setExportDate(String exportDate) {
 45         this.exportDate = exportDate;
 46     }
 47 }
 48 
 49 /**
 50  * 描述生成文件輸的對象
 51  * @author Administrator
 52  *
 53  */
 54 public class ExportDataModel {
 55     
 56     /**
 57      * 成品編號
 58      */
 59     private String productID;
 60     
 61     /**
 62      * 產品價格
 63      */
 64     private double price;
 65     
 66     /**
 67      * 銷售數量
 68      */
 69     private double amount;
 70 
 71     public String getProductID() {
 72         return productID;
 73     }
 74 
 75     public void setProductID(String productID) {
 76         this.productID = productID;
 77     }
 78 
 79     public double getPrice() {
 80         return price;
 81     }
 82 
 83     public void setPrice(double price) {
 84         this.price = price;
 85     }
 86 
 87     public double getAmount() {
 88         return amount;
 89     }
 90 
 91     public void setAmount(double amount) {
 92         this.amount = amount;
 93     }
 94 }
 95 
 96 
 97 /**
 98  * 描述輸出到文件尾內容的對象
 99  * @author Administrator
100  *
101  */
102 public class ExportFooterModel {
103     
104     /**
105      * 輸出人
106      */
107     private String exportUser;
108 
109     public String getExportUser() {
110         return exportUser;
111     }
112 
113     public void setExportUser(String exportUser) {
114         this.exportUser = exportUser;
115     }
116 }
117 
118 /**
119  * 至關於 ConcreteBuilder
120  * @author Administrator
121  *
122  */
123 public class TxtBuilder implements Builder {
124 
125     //用來構建文件的內容,至關於產品
126     private StringBuffer buffer = new StringBuffer();
127     
128     @Override
129     public void builderHeader(ExportHeaderModel ehm) {
130         // TODO Auto-generated method stub
131         buffer.append("分公司編號:"+ehm.getDepID()+",導入日期:"+ehm.getExportDate()+"\n");
132     }
133 
134     @Override
135     public void BuilderBody(Map<String, Collection<ExportDataModel>> bodyData) {
136         // TODO Auto-generated method stub
137         for(String tblName:bodyData.keySet()){
138             buffer.append(tblName+"\n");
139             for(ExportDataModel edm:bodyData.get(tblName)){
140                 buffer.append(edm.getProductID()+",  "+edm.getPrice()+", "+edm.getAmount()+"\n");
141             } 
142         }
143     }
144 
145     @Override
146     public void builderFooter(ExportFooterModel efm) {
147         // TODO Auto-generated method stub
148         buffer.append(efm.getExportUser()+"\n");
149     }
150     
151     public StringBuffer getResult(){
152         return buffer;
153     }
154 }
155 
156 
157 /**
158  * 至關於 ConcreteBuilder
159  * @author Administrator
160  *
161  */
162 public class XmlBuilder implements Builder {
163 
164     //用來構建文件的內容,至關於產品
165     private StringBuffer buffer = new StringBuffer();
166     
167     @Override
168     public void builderHeader(ExportHeaderModel ehm) {
169         // TODO Auto-generated method stub
170         buffer.append("<?xml verson='1.0' encoding='gb2312'?>\n");
171         buffer.append("<Report>\n");
172         buffer.append("   <Header>\n");
173         buffer.append("      <DeptID>"+ehm.getDepID()+"</DeptID>\n");
174         buffer.append("         <ExportDate>"+ehm.getExportDate()+"</ExportDate>\n");
175         buffer.append("   </Header>\n");
176     }
177 
178     @Override
179     public void BuilderBody(Map<String, Collection<ExportDataModel>> bodyData) {
180         // TODO Auto-generated method stub
181         buffer.append("   <Body>\n");
182         for(String tblname:bodyData.keySet()){
183             buffer.append("   <Dates TableName = \""+tblname+"\">\n");
184             for(ExportDataModel edm:bodyData.get(tblname)){
185                 buffer.append("   <Date>\n");
186                 buffer.append("       <ProductID> "+edm.getProductID()+"</ProductID>\n");
187                 buffer.append("       <Price> "+edm.getPrice()+"</Price>\n");
188                 buffer.append("       <Amount> "+edm.getAmount()+"</Amount>\n");
189             }
190         }
191         buffer.append("   <Body>\n");
192     }
193 
194     @Override
195     public void builderFooter(ExportFooterModel efm) {
196         // TODO Auto-generated method stub
197         buffer.append("    <Footer>\n");
198         buffer.append("        <User>"+efm.getExportUser()+"</User>\n");
199         buffer.append("    </Footer>\n");
200         buffer.append("</Report>\n");
201     }
202     
203     public StringBuffer getResult(){
204         return buffer;
205     }
206 
207 }
208 
209 
210 public class Director {
211     
212     private Builder builder;
213     
214     public Director(Builder builder){
215         this.builder = builder;
216     }
217     
218     public void construct(ExportHeaderModel ehm,Map<String,Collection<ExportDataModel>> bodyData,ExportFooterModel efm){
219         builder.builderHeader(ehm);
220         
221         builder.BuilderBody(bodyData);
222         
223         builder.builderFooter(efm);
224     }
225 }
226 
227 
228 public class Client {
229     
230     public static void main(String[] args) {
231         ExportHeaderModel ehm = new ExportHeaderModel();
232         ehm.setDepID("0001");
233         ehm.setExportDate("2019-04-26");
234         
235         ExportDataModel edm = new ExportDataModel();
236         edm.setProductID("cp001");
237         edm.setPrice(5.56);
238         edm.setAmount(133333);
239         
240         ExportDataModel edm2 = new ExportDataModel();
241         edm2.setProductID("cp001");
242         edm2.setPrice(5.56);
243         edm2.setAmount(133333);
244         
245         Map<String,Collection<ExportDataModel>> data = new HashMap<String,Collection<ExportDataModel>>();
246         Collection<ExportDataModel> collect = new ArrayList<ExportDataModel>();
247         
248         collect.add(edm);
249         collect.add(edm2);
250         
251         data.put("bodys", collect);
252         
253         ExportFooterModel efm = new ExportFooterModel();
254         efm.setExportUser("pwg");
255         
256         TxtBuilder tb = new TxtBuilder();
257         Director dr = new Director(tb);
258         
259         dr.construct(ehm, data, efm);
260         
261         System.out.println("輸出到文本文件:"+tb.getResult());
262         
263         XmlBuilder xml = new XmlBuilder();
264         Director dr2 = new Director(xml);
265         dr2.construct(ehm, data, efm);
266         
267         System.out.println("輸出到 xml 文件:\n"+xml.getResult());
268     }
269     
270     
271 }

        上面的代碼例子展現了建造者模式的功能。其中爲了比較好的展現實現了兩個不一樣的產品,實現了兩個不一樣的表示,而 Director 只是實現了一個,可是經過例子能夠看出,若是須要。也能夠實現不一樣 Director ,即產品的組裝過程。這樣產品就是很靈活的擴展性,而且產品的表示和組建過程解耦。blog

   進而分析出建造者模式的本事是區分 複雜對象的建立  和  它的表示  。這兩個在代碼中的體現是 Director  和   XmlBuilder  TxtBuilder。

 分析建造者\生成器模式

       建造者模式應用場景:能夠靈活的、易擴展的建立複雜對象。而解決的辦法就是分離構建算法和具體構造實現。這樣在擴展的時候能夠根據須要切換 構建算法(Director  )和 具體構造實現 (Builder)。只要抓住了這點,基本就理解了生成器的本質了。

相關文章
相關標籤/搜索