Java設計模式--建造者模式【Builder Pattern】

        昨晚回到家裏,我爸爸氣沖沖地跟我訴苦,“哎!,幹個裝修容易麼?顧客啥都不懂,還非得規定裝修順序,要先貼地板磚後刷牆,到時候貼好的地磚上全是泥,哪有這麼幹活的?”老爸幹了一輩子的裝修,一切事宜由他全權負責,難免心力憔悴。但是,我仔細想了下這個事情,如果老爸簽訂了一個公司,公司負責接活攬活,規定裝修要求,老爸只負責執行,那不就輕鬆了嗎?於是我就想起了建造者模式。

      建造者模式的定義是:將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示它允許用戶通過制定的對象類型和內容來創建他們,但是用戶並不需要知道這個複雜對象是如何構建的,它只需要明白通過這樣做我可以得到一個完整的複雜對象實例。

     建造者模式是爲了將構建複雜對象的過程和它的部件解耦。因爲一個複雜的對象,不但有很多大量組成部分,如汽車,有很多部件:車輪方向盤 發動機還有各種小零件等等,部件很多,但遠不止這些,如何將這些部件裝配成一輛汽車,這個裝配過程也很複雜(需要很好的組裝技術),Builder模式就是爲了將部件和組裝過程分開。

   建造者模式主要包含四個角色:

       Director:指揮者,導演類,構建一個使用Builder接口的對象。它主要是用於創建一個複雜的對象,負責調用適當的建造者來組建產品。它主要有兩個作用,一是:隔離了客戶與對象的生產過程,二是:負責控制產品對象的生產過程。

       Builder:抽象建造者。它聲明爲創建一個Product對象的各個部件指定的抽象接口,一般至少會有兩個抽象方法,一個用來建造產品,一個是用來返回產品。
       ConcreteBuilder:具體建造者。實現抽象接口,構建和裝配各個部件,按照要求組建產品和返回組建好的產品。
       Product:產品角色。一個具體的產品對象。

    現在假設老爸上面簽訂了裝修公司,公司負責與客戶對接,按照客戶要求制定裝修的細則和分派裝修人員,然後按期把裝修好的房子提供給顧客。那麼裝修公司就是Director:   

package com.pattern.builder;

import java.util.List;
/**
 * 裝修公司相當於Director--負責安排builder和對應的裝修次序
 * @author 
 *
 */
public class BuilderCompany {
   private Decorator builder;

public BuilderCompany(Decorator builder) {
	this.builder = builder;
}
/**
 * 公司安排裝修次序-讓builder去裝修房子
 * @param sequence
 */
public void decoration(List<String> sequence){
	this.builder.setSequence(sequence);//制定裝修順序
	this.builder.getNiceHouse();//提供裝修好的房子
}   
}
制定一個抽象建造者,提供建造產品和過程的抽象方法:

package com.pattern.builder;

import java.util.ArrayList;
import java.util.List;
/**
 * 裝修者--抽象類
 * 定義裝修的動作 並根據動作順序返回結果
 * @author 
 *
 */
public abstract class Decorator {
   private List<String> sequence = new ArrayList<String>();//裝修順序
   protected abstract void designDrawing();//出設計圖
   protected abstract void transHydropower();//水電改造
   protected abstract void brushWall();//刷牆
   protected abstract void stickTiles();//貼地磚
   protected abstract NiceHouse getNiceHouse();//得到裝修好的漂亮房子
   
   /**
    * 根據裝修公司制定的裝修次序--執行動作 
    */
    final protected void setDecorateSequence(){
	  for(String s:sequence){
		  if(s.equalsIgnoreCase(Sequence.DRAW)){
			  this.designDrawing();
		  }else if(s.equalsIgnoreCase(Sequence.POWER)){
			  this.transHydropower();
		  }else if(s.equalsIgnoreCase(Sequence.BRUSH)){
			  this.brushWall();
		  }else if(s.equalsIgnoreCase(Sequence.TILES)){
			  this.stickTiles();
		  }
	  }
   }
   
/**
 * 設置裝修動作順序  
 * @param sequence
 */
public void setSequence(List<String> sequence) {
	this.sequence = sequence;
}
}
上述爲了編程方便,定義了一個裝修順序的常量類:

package com.pattern.builder;

public class Sequence {
  public static final String DRAW="draw";//出設計圖
  public static final String POWER="power";//水電改造
  public static final String BRUSH="brush";//刷牆
  public static final String TILES="tiles";//貼地磚
}
然後老爸和其他同事按照公司規定的順序負責裝修,按期交工即可:

package com.pattern.builder;
/**
 * 具體建造者A
 * @author 
 *
 */
public class DecoratorZhang extends Decorator{

	@Override
	protected void designDrawing() {	
		System.out.println("DecoratorZhang出設計圖...");
	}

	@Override
	protected void transHydropower() {
		System.out.println("DecoratorZhang水電改造...");
		
	}

	@Override
	protected void brushWall() {
		System.out.println("DecoratorZhang刷牆...");
		
	}

	@Override
	protected void stickTiles() {
		System.out.println("DecoratorZhang貼地磚...");
		
	}

	@Override
	public NiceHouse getNiceHouse() {
		super.setDecorateSequence();
		return new NiceHouse("DecoratorZhang");
	}
}
package com.pattern.builder;
/**
 * 具體建造者B
 * @author 
 *
 */
public class DecoratorLi extends Decorator{

	@Override
	protected void designDrawing() {	
		System.out.println("DecoratorLi出設計圖...");
	}

	@Override
	protected void transHydropower() {
		System.out.println("DecoratorLi水電改造...");
		
	}

	@Override
	protected void brushWall() {
		System.out.println("DecoratorLi刷牆...");
		
	}

	@Override
	protected void stickTiles() {
		System.out.println("DecoratorLi貼地磚...");
		
	}
	@Override
	public NiceHouse getNiceHouse() {
		super.setDecorateSequence();
		return new NiceHouse("DecoratorLi");
	}
}
定義交付的產品類,這裏就是簡單的裝修好的房子:

package com.pattern.builder;
/**
 * 相當於建造者模式中的Product
 * @author 
 *
 */
public class NiceHouse {

   public NiceHouse(String houseName) {
	System.out.println(houseName+"裝修房子煥然一新啦!\n");
   }      
}
測試類:N天后,顧客來到公司,說我的房子裝修好了嗎?快帶我看看:

package com.pattern.builder;

import java.util.ArrayList;
import java.util.List;
/**
 * 測試類 Customer
 * @author 
 *
 */
public class Customer {
    public static void main(String[] args){
    	/**
    	 * 顧客來到裝修公司,說我要裝修兩套房子
    	 * 第一套  你先給我出個設計圖,然後水電改造,刷牆,貼磚
    	 * 第二套  你先給我水電改造,再出設計圖,貼磚,刷牆
    	 * 我們籤個合同吧,按期給我裝修好,BYE BYE
    	 * 簽好合同後,裝修公司設計好兩套房子的裝修順序,並安排老張和老李分別負責執行
    	 */
    	
    	//第一套房子
    	List<String> sequence1=new ArrayList<String>();
    	sequence1.add(Sequence.DRAW);
    	sequence1.add(Sequence.POWER);
    	sequence1.add(Sequence.BRUSH);
    	sequence1.add(Sequence.TILES);
    	DecoratorZhang dzhang=new DecoratorZhang();
    	BuilderCompany c1=new BuilderCompany(dzhang);
    	c1.decoration(sequence1);
    	
    	//第二套房子
    	List<String> sequence2=new ArrayList<String>();
    	sequence2.add(Sequence.POWER);
    	sequence2.add(Sequence.DRAW);
    	sequence2.add(Sequence.TILES);
      	sequence2.add(Sequence.BRUSH);
    	DecoratorLi dli=new DecoratorLi();
    	BuilderCompany c2=new BuilderCompany(dli);
    	c2.decoration(sequence2);	
    }
}

     可以看到,建造者模式與工廠模式是極爲相似的建造者模式僅僅只比工廠模式多了一個“導演類”的角色。如果把這個導演類看做是最終調用的客戶端(客戶),那麼圖中剩餘的部分就可以看作是一個簡單的工廠模式了。與工廠模式相比,建造者模式一般用來創建更爲複雜的對象,因爲對象的創建過程更爲複雜,因此將對象的創建過程獨立出來組成一個新的類——導演類。也就是說,工廠模式是將對象的全部創建過程封裝在工廠類中,由工廠類向客戶端提供最終的產品;而建造者模式中,建造者類一般只提供產品類中各個組件的建造,而將具體建造過程交付給導演類。由導演類負責將各個組件按照特定的規則組建爲產品,然後將組建好的產品交付給客戶端。

  優點:

       1、將複雜產品的創建步驟分解在不同的方法中,使得我們能夠更加精確的控制複雜對象的產生過程。

       2、將產品的創建過程與產品本身分離開來,可以使用相同的創建過程來得到不同的產品。

       3、每一個具體建造者都相對獨立,具有良好的擴展性,使用不同的具體建造者即可得到不同的產品對象。

       4、客戶端無需關心創建產品的具體細節,統一由“導演類”指定生產過程,調用建造者創建產品。

    缺點:

       1、建造者模式所創建的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用範圍受到一定的限制。
       2、如果產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。



源碼下載:http://download.csdn.net/download/pelifymeng2/9994100

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