java 開發模式之十六 : 生成器模式

原理或定義

將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表

結構

Builder:生成器接口,定義創建一個Product對象所需要的各個部件的操作。

ConcreteBuilder:具體的生成器實現,實現各個部件的創建,並負責組裝Product對象的各個部件,同時還提供一個讓用戶獲取組裝完成後的產品對象的方法。

Director:指導者,也被稱導向者,主要用來使用Builder接口,以一個統一的過程來構建所需要的Product對象。

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

 

類圖

案例與代碼

本文使用度假計劃生成項目來介紹

度假計劃生成項目介紹
度假計劃的因素:時間、門票、餐廳、住宿、特殊活動等

生成器模式設計方案:


類圖:


Product:

public class VacationDay {
	private Date mDate;
	private String mHotels;
	private ArrayList<String> mTickets = null;
	private ArrayList<String> mEvents = null;

	public VacationDay(Date date) {
		mDate = date;
		mTickets = new ArrayList<String>();
		mEvents = new ArrayList<String>();
	}

	public void setDate(Date date) {
		mDate = date;
	}

	public void setHotel(String mHotels) {
		this.mHotels = mHotels;
	}

	public void addTicket(String ticket) {
		mTickets.add(ticket);
	}

	public void addEvent(String event) {
		mEvents.add(event);
	}

	public String showInfo() {
		StringBuilder stb = new StringBuilder();
		stb.append("Date:" + mDate.toString() + "\n");
		stb.append("Hotel:" + mHotels + "\n");
		stb.append("Tickets:" + mTickets.toString() + "\n");
		stb.append("Events" + mEvents.toString() + "\n");

		return stb.toString();
	}
}
public class Vacation {
	private ArrayList<VacationDay> mVacationDayLst;
	private Date mStDate;
	private int mDays = 0;
	private VacationDay mVacationDay;


	public Vacation(String std) {
		mVacationDayLst = new ArrayList<VacationDay>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			mStDate = sdf.parse(std);
			mVacationDay = new VacationDay(mStDate);
			mVacationDayLst.add(mVacationDay);
			mDays++;
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	public void setStDate(String std) {


		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			mStDate = sdf.parse(std);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


	}


	public Date getStDate() {


		return mStDate;
	}


	public void addDay() {


		mVacationDay = new VacationDay(nextDate(mDays));
		mVacationDayLst.add(mVacationDay);
		mDays++;
	}


	public boolean setVacationDay(int i) {
		if ((i > 0) && (i < mVacationDayLst.size())) {
			mVacationDay = mVacationDayLst.get(i);
			return true;
		}
		mVacationDay = null;
		return false;
	}


	public void setHotel(String mHotels) {
		mVacationDay.setHotel(mHotels);
	}


	public void addTicket(String ticket) {
		mVacationDay.addTicket(ticket);
	}


	public void addEvent(String event) {
		mVacationDay.addEvent(event);
	}


	public void showInfo() {
		for (int i = 0, len = mVacationDayLst.size(); i < len; i++) {
			System.out.println("** " + (i + 1) + " day**");
			System.out.println(mVacationDayLst.get(i).showInfo());


		}
	}


	private Date nextDate(int n) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(mStDate);
		cal.add(Calendar.DATE, n);
		return cal.getTime();
	}
}

Builder

public abstract class AbsBuilder {

	public Vacation mVacation;

	public AbsBuilder(String std) {
		mVacation = new Vacation(std);
	}

	public abstract void buildvacation();

	public abstract void buildDay(int i);

	public abstract void addHotel(String hotel);

	public abstract void addTicket(String ticket);

	public abstract void addEvent(String tvent);

	public Vacation getVacation() {

		return mVacation;

	}

}

ConcreteBuilder

public class Builder3d extends AbsBuilder {

	public Builder3d(String std) {
		super(std);
		// TODO Auto-generated constructor stub

	}

	@Override
	public void buildDay(int i) {
		// TODO Auto-generated method stub

		mVacation.setVacationDay(i);

	}

	@Override
	public void addHotel(String hotel) {
		// TODO Auto-generated method stub
		mVacation.setHotel(hotel);
	}

	@Override
	public void addTicket(String ticket) {
		// TODO Auto-generated method stub
		mVacation.addTicket(ticket);
	}

	@Override
	public void addEvent(String event) {
		// TODO Auto-generated method stub
		mVacation.addEvent(event);
	}

	@Override
	public void buildvacation() {
		// TODO Auto-generated method stub
		addTicket("Plane Ticket");
		addEvent("Fly to Destination");
		addEvent("Supper");
		addEvent("Dancing");
		addHotel("Four Seasons");

		mVacation.addDay();
		addTicket("Theme Park");
		addEvent("Bus to Park");
		addEvent("lunch");
		addHotel("Four Seasons");

		mVacation.addDay();

		addTicket("Plane Ticket");
		addEvent("City Tour");
		addEvent("Fly to Home");

	}

}
public class Builder4d extends AbsBuilder {


	public Builder4d(String std) {
		super(std);
		// TODO Auto-generated constructor stub


	}


	@Override
	public void buildDay(int i) {
		// TODO Auto-generated method stub


		mVacation.setVacationDay(i);


	}


	@Override
	public void addHotel(String hotel) {
		// TODO Auto-generated method stub
		mVacation.setHotel(hotel);
	}


	@Override
	public void addTicket(String ticket) {
		// TODO Auto-generated method stub
		mVacation.addTicket(ticket);
	}


	@Override
	public void addEvent(String event) {
		// TODO Auto-generated method stub
		mVacation.addEvent(event);
	}


	@Override
	public void buildvacation() {
		// TODO Auto-generated method stub
		addTicket("Plane Ticket");
		addEvent("Fly to Destination");
		addEvent("Supper");
		addHotel("Hilton");


		mVacation.addDay();
		addTicket("Zoo Ticket");
		addEvent("Bus to Zoo");
		addEvent("Feed animals");
		addHotel("Hilton");


		mVacation.addDay();
		addTicket("Beach");
		addEvent("Swimming");
		addHotel("Home inn");


		mVacation.addDay();
		addTicket("Plane Ticket");
		addEvent("Fly to Home");
	}


}
public class BuilderSelf {
	public Vacation mVacation;


	public BuilderSelf(String std) {
		mVacation = new Vacation(std);
		// TODO Auto-generated constructor stub


	}


	public BuilderSelf addDay() {
		// TODO Auto-generated method stub


		mVacation.addDay();
		return this;
	}


	public BuilderSelf buildDay(int i) {
		// TODO Auto-generated method stub


		mVacation.setVacationDay(i);
		return this;
	}


	public BuilderSelf addHotel(String hotel) {
		// TODO Auto-generated method stub
		mVacation.setHotel(hotel);
		return this;
	}


	public BuilderSelf addTicket(String ticket) {
		// TODO Auto-generated method stub
		mVacation.addTicket(ticket);
		return this;
	}


	public BuilderSelf addEvent(String event) {
		// TODO Auto-generated method stub
		mVacation.addEvent(event);
		return this;
	}


	public Vacation getVacation() {


		return mVacation;


	}
}

Director

public class Director {
	private AbsBuilder builder;
	
	public Director(AbsBuilder builder)
	{
		this.builder=builder;
	}
	public void setBuilder(AbsBuilder builder)
	{
		this.builder=builder;
	}
	public void construct()
	{
		builder.buildvacation();
		builder.getVacation().showInfo();
	}
}

測試類:

public class MainTest {

	public static void main(String[] args) {

		Director mDirector = new Director(new Builder4d("2015-12-29"));

		mDirector.construct();

		mDirector.setBuilder(new Builder3d("2015-8-30"));
		mDirector.construct();
		testself() ;
	}

	public static void testself() {
		BuilderSelf builder = new BuilderSelf("2015-9-29");

		builder.addTicket("Plane Ticket").addEvent("Fly to Destination")
				.addEvent("Supper").addHotel("Hilton");

		builder.addDay().addTicket("Zoo Ticket").addEvent("Bus to Zoo")
				.addEvent("Feed animals").addHotel("Home Inn");

		builder.addDay();
		builder.addTicket("Beach");
		builder.addEvent("Swimming");
		builder.addHotel("Home inn");

		builder.addDay().addTicket("Plane Ticket").addEvent("Fly to Home");
		builder.getVacation().showInfo();
	}

}

封裝一個複雜對象構造過程,並允許按步驟構造。


生成器模式2種演化形式:

省略抽象生成器類
省略指導者類


使用場景

1. 需要生成一個產品對象有複雜的內部結構。每一個內部成分本身可以是對象,也可以使一個對象的一個組成部分。
        2、生成的產品對象的屬性相互依賴。建造模式可以強制實行一種分步驟進行的建造過程。
        3、在對象創建過程中會使用到系統中的其他一些對象,這些對象在產品對象的創建過程中不易得到

優缺點

主要優點有:

1. 生成器模式正是把產品構建的過程獨立出來,使它和具體產品的表現分鬆散耦合,從而使得構建算法可以複用,而具體產品表現也可以很靈活地、方便地擴展和切換

2. 由於Builder對象只是提供接口給Director使用,那麼具體部件創建和裝配方式是被Builder接口隱藏了的,Director並不知道這些具體的實現細節

3. 生成器模式很好的實現構建算法和具體產品實現的分離。這樣一來,使得構建產品的算法可以複用。同樣的道理,具體產品的實現也可以複用,同一個產品的實現,可以配合不同的構建算法使用

4. 分離整體構建算法和部件構造

 

缺點主要有

建造者模式的加工工藝是暴露的,這樣使得建造者模式更加靈活,也使得工藝變得對客戶不透明

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