JAVA設計模式-Builder

Builder設計模式類似於Factory,都是用於生產一種產品,但是他們之間還是有一些區別的。至於有什麼區別,仁者見仁,智者見智,我會在介紹完Builder模式之後說說我自己的看法,當然我的想法也參考了很多其他人的看法。下面先看一個例子吧:

 

    當要生產的一種產品具有相同的結構,並且每個構件的生產都很繁雜,就可以用Builder模式將具體構件的生產與整個成品的組裝分離開來。還是拿本文的代碼來舉例,生產一輛汽車,生產汽車的廠家不需要知道引擎怎麼生產的,不需要關心輪胎怎麼生產的,也不需要關心玻璃怎麼生產的。當他在生產一輛車的時候,只會說,我要一塊日本產的引擎,於是就有了日本產的引擎(至於日本引擎怎麼生產的他不關心,他只要一個引擎的成品),他又說我要一塊美國產的玻璃,於是就有了美國產的玻璃,這樣直到他得到了所有的構件,然後他把這些構件組裝起來,組成一個成品(汽車)賣給客戶。這就是一個典型的Builder模式。下面是代碼:

 

 

  1. package builder;  
  2. /** 
  3.  * design pattern in java 
  4.  * name:builder 
  5.  * 目的:利用builder模式創建兩種汽車carA和carB 
  6.  * car=glass+wheel+engine 
  7.  * carA=AmericanGlass+JapaneseWheel+ChinaEngine 
  8.  * carB=JapaneseGlass+AmericanWheel+FranceEngine 
  9.  * author:blackphoenix 
  10.  * create date:2002-08-19 
  11.  * modifier:Anyuan Zhao 
  12.  * modify date:2011-02-16 
  13.  */  
  14.   
  15. /** 
  16.  * 定義部件glass的抽象類Glass 
  17.  * 和兩個具體類AmericanGlass、JapaneseGlass 
  18.  */  
  19. abstract class Glass{  
  20. }  
  21. class AmericanGlass extends Glass{  
  22.     public String toString(){  
  23.         return "/"American Glass/" ";  
  24.     }  
  25. }  
  26. class JapaneseGlass extends Glass{  
  27.     public String toString(){  
  28.         return "/"Japanese Glass/" ";  
  29.     }  
  30. }  
  31.   
  32. /** 
  33.  * 定義部件wheel的抽象類Wheel 
  34.  * 和兩個具體類AmericanWheel、JapaneseWheel 
  35.  */  
  36. abstract class Wheel{  
  37. }  
  38. class AmericanWheel extends Wheel{  
  39.     public String toString(){  
  40.         return "/"American Wheel/" ";  
  41.     }  
  42. }  
  43. class JapaneseWheel extends Wheel{  
  44.     public String toString(){  
  45.         return "/"Japanese Wheel/" ";  
  46.     }  
  47. }  
  48.   
  49. /** 
  50.  * 定義部件engine的抽象類Engine 
  51.  * 和兩個具體類ChineseEngine、FranceEngine 
  52.  */  
  53. abstract class Engine{  
  54. }  
  55. class ChineseEngine extends Engine{  
  56.     public String toString(){  
  57.         return "/"Chinese Engine/" ";  
  58.     }  
  59. }  
  60. class FranceEngine extends Engine{  
  61.     public String toString(){      
  62.         return "/"France Engine/" ";  
  63.     }  
  64. }  
  65.   
  66. /** 
  67.  * 定義產品類Car 
  68.  */  
  69. class Car{  
  70.     Glass glass;  
  71.     Wheel wheel;  
  72.     Engine engine;  
  73. }  
  74. /** 
  75.  * 定義抽象建造器接口Builder 
  76.  */  
  77.   
  78. interface CarBuilder{  
  79.     public void buildGlass();  
  80.     public void buildWheel();  
  81.     public void buildEngine();  
  82.     public Car getProduct();  
  83. }  
  84.   
  85. /** 
  86.  * 具體建造器類CarABuilder 
  87.  * CarA=AmericanGlass+JapaneseWheel+ChineseEngine 
  88.  */  
  89. class CarABuilder implements CarBuilder{  
  90.     private Car product=null;  
  91.     public CarABuilder(){  
  92.         product=new Car();  
  93.     }  
  94.     /** 
  95.      * 將建造部件的工作封裝在getProduct()操作中,主要是爲了向客戶隱藏實現細節 
  96.      * 這樣,具體建造類同時又起到了一個director的作用 
  97.      */  
  98.     @Override  
  99.     public void buildEngine() {  
  100.         // TODO Auto-generated method stub   
  101.         product.engine=new ChineseEngine();  
  102.     }  
  103.     @Override  
  104.     public void buildGlass() {  
  105.         // TODO Auto-generated method stub   
  106.         product.glass=new AmericanGlass();  
  107.     }  
  108.     @Override  
  109.     public void buildWheel() {  
  110.         // TODO Auto-generated method stub   
  111.         product.wheel=new JapaneseWheel();  
  112.     }  
  113.     @Override  
  114.     public Car getProduct() {  
  115.         // TODO Auto-generated method stub   
  116.         buildGlass();  
  117.         buildWheel();  
  118.         buildEngine();  
  119.         return product;  
  120.     }  
  121. }  
  122. /** 
  123.  * 具體建造器類CarABuilder 
  124.  * CarB=JapaneseGlass+AmericanWheel+FranceEngine 
  125.  */  
  126. class CarBBuilder implements CarBuilder{  
  127.     private Car product;  
  128.     public CarBBuilder(){  
  129.         product=new Car();  
  130.     }  
  131.     /** 
  132.      * 將建造部件的工作封裝在getProduct()操作中,主要是爲了向客戶隱藏實現細節 
  133.      * 這樣,具體建造類同時又起到了一個director的作用 
  134.      */  
  135.     @Override  
  136.     public void buildEngine() {  
  137.         // TODO Auto-generated method stub   
  138.         product.engine=new FranceEngine();  
  139.     }  
  140.     @Override  
  141.     public void buildGlass() {  
  142.         // TODO Auto-generated method stub   
  143.         product.glass=new JapaneseGlass();  
  144.     }  
  145.     @Override  
  146.     public void buildWheel() {  
  147.         // TODO Auto-generated method stub   
  148.         product.wheel=new AmericanWheel();  
  149.     }  
  150.     @Override  
  151.     public Car getProduct() {  
  152.         // TODO Auto-generated method stub   
  153.         buildGlass();  
  154.         buildWheel();  
  155.         buildEngine();  
  156.         return product;  
  157.     }  
  158. }  
  159. class Director{  
  160.     private CarBuilder builder;   
  161.     public Director(CarBuilder builder) {   
  162.         this.builder = builder;   
  163.     }  
  164.     public Car construct() {   
  165.         return builder.getProduct();  
  166.     }   
  167. }  
  168. /** 
  169.  * 客戶端代碼,使用Director創建兩種不同型別的CarA和CarB 
  170.  */  
  171. public class Test{  
  172.     public static void main(String[] args){  
  173.         Car carA,carB;  
  174.         CarBuilder builderA = new CarABuilder();  
  175.         CarBuilder builderB = new CarBBuilder();  
  176.         Director director;  
  177.         director = new Director(builderA);  
  178.         carA=director.construct();  
  179.         director = new Director(builderB);  
  180.         carB=director.construct();  
  181.         System.out.println("Car A is made by:"+carA.glass+carA.wheel+carA.engine);  
  182.         System.out.println("Car B is made by:"+carB.glass+carB.wheel+carB.engine);  
  183.     }  
  184. }  

 

    這個代碼的運行結果:

    Car A is made by:"American Glass" "Japanese Wheel" "Chinese Engine"

    Car B is made by:"Japanese Glass" "American Wheel" "France Engine"

 

    首先要解釋一下toString()這個方法(和Builder模式無關,只是順帶提一下),他是重載了Object的toString()方法,當使用System.out.println(object)的時候,就會隱式調用object的toString()方法。

 

    解釋下代碼,在main函數裏面,director調用了builder裏面的getProduct()方法,getProduct()方法實際就是組裝的過程,getProduct()裏面的buildGlass(),buildWheel(),buildEngine()就是在購買構件,而這些構件生產的具體過程放在了這些構件自身的類裏面,可以看到buildGlass()裏面有new一個對象,這就是在進行生產。這樣就達到了組裝和生產構件之間的分離。

 

    最後,說說我對Builder模式和Factory模式之間區別的理解。我個人認爲Builder和Factory之間的區別就是組裝和生產之間的區別,Builder着重將組裝和構件的生產分離,Factory着重於優化生產的過程。本文的代碼實際上還可以進行重構,例如,在buildGlass()函數裏面,用到了new這個關鍵字,實際上可以將這個new換成工廠類,讓工廠類來生產Glass。換一種說法,就是Factory不進行組裝,Builder進行組裝,當Factory進行組裝的時候,它就變成Builder了。

 

    我也不知道我說清楚沒,這只是我個人看法而已,僅供參考,不是標準答案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章