原理或定義
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
結構
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. 分離整體構建算法和部件構造
缺點主要有:
建造者模式的“加工工藝”是暴露的,這樣使得建造者模式更加靈活,也使得工藝變得對客戶不透明。