24种设计模式-生成器模式
1. 什么是生成器模式
Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23種設計模式中的一種。Builder模式是一種對象創(chuàng)建型模式之一,用來隱藏復合對象的創(chuàng)建過程,它把復合對象的創(chuàng)建過程加以抽象,通過子類繼承和重載的方式,動態(tài)地創(chuàng)建具有復合屬性的對象。
簡單來說就是封裝一個復雜對象的構造過程,并允許按照步驟構造。
生成器模式的結構:
- 對象的創(chuàng)建:Builder模式是為對象的創(chuàng)建而設計的模式
- 創(chuàng)建的是一個復合對象:被創(chuàng)建的對象為一個具有復合屬性的復合對象
- 關注對象創(chuàng)建的各部分的創(chuàng)建過程:不同的工廠(這里指builder生成器)對產品屬性有不同的創(chuàng)建方法
適用場景:
- 需要生成的產品對象有復雜的內部結構,這些產品對象通常包含多個成員屬性。
- 需要生成的產品對象的屬性相互依賴,需要指定其生成順序。
- 對象的創(chuàng)建過程獨立于創(chuàng)建該對象的類。在建造者模式中通過引入了指揮者類,將創(chuàng)建過程封裝在指揮者類中,而不在建造者類和客戶類中。
- 隔離復雜對象的創(chuàng)建和使用,并使得相同的創(chuàng)建過程可以創(chuàng)建不同的產品。
優(yōu)缺點:
優(yōu)點:
-
封裝性很好:使用建造者模式可以有效的封裝變化,在使用建造者模式的場景中,一般產品類和建造者類是比較穩(wěn)定的,因此,將主要的業(yè)務邏輯封裝在導演類中對整體而言可以取得比較好的穩(wěn)定性。
-
擴展性很好:建造者模式很容易進行擴展。如果有新的需求,通過實現(xiàn)一個新的建造者類就可以完成,基本上不用修改之前已經測試通過的代碼,因此也就不會對原有功能引入風險。
-
有效控制細節(jié)風險:由于具體的建造者是獨立的,因此可以對建造者過程逐步細化,而不對其他的模塊產生任何影響。
-
將復雜對象的創(chuàng)建過程封裝起來
-
允許對象通過幾個步驟來創(chuàng)建,并且可以改變過程(工廠模式只有一個步驟)
-
只需指定具體生成器就能生成特定對象,隱藏類的內部結構
對象的實現(xiàn)可以被替換
缺點:
- 建造者模式所創(chuàng)建的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用范圍受到一定的限制。
- 如果產品的內部變化復雜,可能會導致需要定義很多具體建造者類來實現(xiàn)這種變化,導致系統(tǒng)變得很龐大。
2. 具體實例
這里舉一個具體的例子來介紹生成器模式是怎么使用的.
度假計劃生成項目:就是一個公司要推出度假的活動,然后會有具體的安排計劃。
度假計劃的因素:時間、門票、餐廳、住宿、特殊活動等。
所以我們就像抽象一個度假類,然后每一天去繼承和擴展這個類。所以類圖如下:
這樣一個計劃就是一個具體對象,便于擴展。
然后我們基于上面的基礎,我們想用戶可以自己選擇具體是怎么過?選什么樣的方式,就是我選3天的度假模式,還是選四天的度假模式,或者是其他種類的。這樣的話我們就需要在設計一個抽象類AbsBuilder的類,然后在這個類中實現(xiàn)Vaction,然后用戶通過Director就可以自行選擇具體是什么樣的度假模式,不用管底層的實現(xiàn),直接使用這個類就可以了。然后要添加新的度假類的時候也不需要修改,符合開閉原則。具體的類圖如下:
具體的代碼實現(xiàn):
Vacation:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 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 blocke.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 blocke.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();} } |
VacationDay:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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();} } |
抽象類AbsBuilder:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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;} } |
具體的度假模式(3天):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | public class Builder3d extends AbsBuilder {public Builder3d(String std) {super(std);// TODO Auto-generated constructor stub}@Overridepublic void buildDay(int i) {// TODO Auto-generated method stubmVacation.setVacationDay(i);}@Overridepublic void addHotel(String hotel) {// TODO Auto-generated method stubmVacation.setHotel(hotel);}@Overridepublic void addTicket(String ticket) {// TODO Auto-generated method stubmVacation.addTicket(ticket);}@Overridepublic void addEvent(String event) {// TODO Auto-generated method stubmVacation.addEvent(event);}@Overridepublic void buildvacation() {// TODO Auto-generated method stubaddTicket("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");} } |
4天的模式:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public class Builder4d extends AbsBuilder {public Builder4d(String std) {super(std);// TODO Auto-generated constructor stub}@Overridepublic void buildDay(int i) {// TODO Auto-generated method stubmVacation.setVacationDay(i);}@Overridepublic void addHotel(String hotel) {// TODO Auto-generated method stubmVacation.setHotel(hotel);}@Overridepublic void addTicket(String ticket) {// TODO Auto-generated method stubmVacation.addTicket(ticket);}@Overridepublic void addEvent(String event) {// TODO Auto-generated method stubmVacation.addEvent(event);}@Overridepublic void buildvacation() {// TODO Auto-generated method stubaddTicket("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");} } |
Director:在Director中傳入Builder,然后構造的時候實現(xiàn)vacation的實例化。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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();} } |
測試類:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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();} } |
3. 生成器模式與抽象工廠的差異
生成器模式和抽象工廠模式在功能上很相似,主要區(qū)別:
- 生成器一般用來創(chuàng)建大的復雜的對象
- 生成器模式強調的是一步步創(chuàng)建對象,可以改變步驟來生成不同的對象
- 一般來說生成器模式中對象不直接返回
總結
以上是生活随笔為你收集整理的24种设计模式-生成器模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOS 7.4 安装网易云音乐
- 下一篇: 设计模式 - 建造者模式/生成器模式