當要生產的一種產品具有相同的結構,並且每個構件的生產都很繁雜,就可以用Builder模式將具體構件的生產與整個成品的組裝分離開來。還是拿本文的代碼來舉例,生產一輛汽車,生產汽車的廠家不需要知道引擎怎麼生產的,不需要關心輪胎怎麼生產的,也不需要關心玻璃怎麼生產的。當他在生產一輛車的時候,只會說,我要一塊日本產的引擎,於是就有了日本產的引擎(至於日本引擎怎麼生產的他不關心,他只要一個引擎的成品),他又說我要一塊美國產的玻璃,於是就有了美國產的玻璃,這樣直到他得到了所有的構件,然後他把這些構件組裝起來,組成一個成品(汽車)賣給客戶。這就是一個典型的Builder模式。下面是代碼:
- package builder;
- /**
- * design pattern in java
- * name:builder
- * 目的:利用builder模式創建兩種汽車carA和carB
- * car=glass+wheel+engine
- * carA=AmericanGlass+JapaneseWheel+ChinaEngine
- * carB=JapaneseGlass+AmericanWheel+FranceEngine
- * author:blackphoenix
- * create date:2002-08-19
- * modifier:Anyuan Zhao
- * modify date:2011-02-16
- */
- /**
- * 定義部件glass的抽象類Glass
- * 和兩個具體類AmericanGlass、JapaneseGlass
- */
- abstract class Glass{
- }
- class AmericanGlass extends Glass{
- public String toString(){
- return "/"American Glass/" ";
- }
- }
- class JapaneseGlass extends Glass{
- public String toString(){
- return "/"Japanese Glass/" ";
- }
- }
- /**
- * 定義部件wheel的抽象類Wheel
- * 和兩個具體類AmericanWheel、JapaneseWheel
- */
- abstract class Wheel{
- }
- class AmericanWheel extends Wheel{
- public String toString(){
- return "/"American Wheel/" ";
- }
- }
- class JapaneseWheel extends Wheel{
- public String toString(){
- return "/"Japanese Wheel/" ";
- }
- }
- /**
- * 定義部件engine的抽象類Engine
- * 和兩個具體類ChineseEngine、FranceEngine
- */
- abstract class Engine{
- }
- class ChineseEngine extends Engine{
- public String toString(){
- return "/"Chinese Engine/" ";
- }
- }
- class FranceEngine extends Engine{
- public String toString(){
- return "/"France Engine/" ";
- }
- }
- /**
- * 定義產品類Car
- */
- class Car{
- Glass glass;
- Wheel wheel;
- Engine engine;
- }
- /**
- * 定義抽象建造器接口Builder
- */
- interface CarBuilder{
- public void buildGlass();
- public void buildWheel();
- public void buildEngine();
- public Car getProduct();
- }
- /**
- * 具體建造器類CarABuilder
- * CarA=AmericanGlass+JapaneseWheel+ChineseEngine
- */
- class CarABuilder implements CarBuilder{
- private Car product=null;
- public CarABuilder(){
- product=new Car();
- }
- /**
- * 將建造部件的工作封裝在getProduct()操作中,主要是爲了向客戶隱藏實現細節
- * 這樣,具體建造類同時又起到了一個director的作用
- */
- @Override
- public void buildEngine() {
- // TODO Auto-generated method stub
- product.engine=new ChineseEngine();
- }
- @Override
- public void buildGlass() {
- // TODO Auto-generated method stub
- product.glass=new AmericanGlass();
- }
- @Override
- public void buildWheel() {
- // TODO Auto-generated method stub
- product.wheel=new JapaneseWheel();
- }
- @Override
- public Car getProduct() {
- // TODO Auto-generated method stub
- buildGlass();
- buildWheel();
- buildEngine();
- return product;
- }
- }
- /**
- * 具體建造器類CarABuilder
- * CarB=JapaneseGlass+AmericanWheel+FranceEngine
- */
- class CarBBuilder implements CarBuilder{
- private Car product;
- public CarBBuilder(){
- product=new Car();
- }
- /**
- * 將建造部件的工作封裝在getProduct()操作中,主要是爲了向客戶隱藏實現細節
- * 這樣,具體建造類同時又起到了一個director的作用
- */
- @Override
- public void buildEngine() {
- // TODO Auto-generated method stub
- product.engine=new FranceEngine();
- }
- @Override
- public void buildGlass() {
- // TODO Auto-generated method stub
- product.glass=new JapaneseGlass();
- }
- @Override
- public void buildWheel() {
- // TODO Auto-generated method stub
- product.wheel=new AmericanWheel();
- }
- @Override
- public Car getProduct() {
- // TODO Auto-generated method stub
- buildGlass();
- buildWheel();
- buildEngine();
- return product;
- }
- }
- class Director{
- private CarBuilder builder;
- public Director(CarBuilder builder) {
- this.builder = builder;
- }
- public Car construct() {
- return builder.getProduct();
- }
- }
- /**
- * 客戶端代碼,使用Director創建兩種不同型別的CarA和CarB
- */
- public class Test{
- public static void main(String[] args){
- Car carA,carB;
- CarBuilder builderA = new CarABuilder();
- CarBuilder builderB = new CarBBuilder();
- Director director;
- director = new Director(builderA);
- carA=director.construct();
- director = new Director(builderB);
- carB=director.construct();
- System.out.println("Car A is made by:"+carA.glass+carA.wheel+carA.engine);
- System.out.println("Car B is made by:"+carB.glass+carB.wheel+carB.engine);
- }
- }
這個代碼的運行結果:
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了。
我也不知道我說清楚沒,這只是我個人看法而已,僅供參考,不是標準答案。