设计模式学习-建造者模式
1.定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2.类图
3.代码示例
1 package com.zhaoyangwoo.builder; 2 3 /** 4 * Created by john on 16/5/7. 5 * 场景类 6 */ 7 public class Builder { 8 9 public static void Main(){ 10 BuilderInterface bi = new ConceptBuilder(); 11 Director director = new Director(); 12 director.construct(bi); 13 } 14 15 } 16 17 /** 18 * 导演类 19 */ 20 class Director { 21 Product construct(BuilderInterface bi){ 22 bi.setProductPartA(); 23 bi.setProductPartB(); 24 return bi.getProduct(); 25 } 26 } 27 28 /** 29 * 抽象建造者 30 */ 31 interface BuilderInterface{ 32 void setProductPartA(); 33 void setProductPartB(); 34 Product getProduct(); 35 } 36 37 /** 38 * 具体建造者 39 */ 40 class ConceptBuilder implements BuilderInterface{ 41 42 private Product product = new Product(); 43 44 @Override 45 public void setProductPartA() { 46 product.setName("产品A"); 47 } 48 49 @Override 50 public void setProductPartB() { 51 product.setPrice(1.111); 52 } 53 54 @Override 55 public Product getProduct() { 56 return product; 57 } 58 } 59 60 61 /** 62 * 具体产品 63 */ 64 class Product{ 65 public String getName() { 66 return name; 67 } 68 69 public void setName(String name) { 70 this.name = name; 71 } 72 73 String name; 74 75 public double getPrice() { 76 return price; 77 } 78 79 public void setPrice(double price) { 80 this.price = price; 81 } 82 83 double price; 84 }
4.应用场景举例
- 创建更复杂对象,隔离对象创建的具体过程
5.JDK源码中的模式实现
Calendar.Builder静态类就是典型的建造者模式,我们来看源码
1 public Calendar build() { 2 if (locale == null) { 3 locale = Locale.getDefault(); 4 } 5 if (zone == null) { 6 zone = TimeZone.getDefault(); 7 } 8 Calendar cal; 9 if (type == null) { 10 type = locale.getUnicodeLocaleType("ca"); 11 } 12 if (type == null) { 13 if (locale.getCountry() == "TH" 14 && locale.getLanguage() == "th") { 15 type = "buddhist"; 16 } else { 17 type = "gregory"; 18 } 19 } 20 switch (type) { 21 case "gregory": 22 cal = new GregorianCalendar(zone, locale, true); 23 break; 24 case "iso8601": 25 GregorianCalendar gcal = new GregorianCalendar(zone, locale, true); 26 // make gcal a proleptic Gregorian 27 gcal.setGregorianChange(new Date(Long.MIN_VALUE)); 28 // and week definition to be compatible with ISO 8601 29 setWeekDefinition(MONDAY, 4); 30 cal = gcal; 31 break; 32 case "buddhist": 33 cal = new BuddhistCalendar(zone, locale); 34 cal.clear(); 35 break; 36 case "japanese": 37 cal = new JapaneseImperialCalendar(zone, locale, true); 38 break; 39 default: 40 throw new IllegalArgumentException("unknown calendar type: " + type); 41 } 42 cal.setLenient(lenient); 43 if (firstDayOfWeek != 0) { 44 cal.setFirstDayOfWeek(firstDayOfWeek); 45 cal.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek); 46 } 47 if (isInstantSet()) { 48 cal.setTimeInMillis(instant); 49 cal.complete(); 50 return cal; 51 } 52 53 if (fields != null) { 54 boolean weekDate = isSet(WEEK_YEAR) 55 && fields[WEEK_YEAR] > fields[YEAR]; 56 if (weekDate && !cal.isWeekDateSupported()) { 57 throw new IllegalArgumentException("week date is unsupported by " + type); 58 } 59 60 // Set the fields from the min stamp to the max stamp so that 61 // the fields resolution works in the Calendar. 62 for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) { 63 for (int index = 0; index <= maxFieldIndex; index++) { 64 if (fields[index] == stamp) { 65 cal.set(index, fields[NFIELDS + index]); 66 break; 67 } 68 } 69 } 70 71 if (weekDate) { 72 int weekOfYear = isSet(WEEK_OF_YEAR) ? fields[NFIELDS + WEEK_OF_YEAR] : 1; 73 int dayOfWeek = isSet(DAY_OF_WEEK) 74 ? fields[NFIELDS + DAY_OF_WEEK] : cal.getFirstDayOfWeek(); 75 cal.setWeekDate(fields[NFIELDS + WEEK_YEAR], weekOfYear, dayOfWeek); 76 } 77 cal.complete(); 78 } 79 80 return cal; 81 }
另外StringBuilder也同样是建造者模式的典型应用
6.思考
- 建造者模式和工厂模式
两者非常相似,把握异同的关键点在于:建造者关注的是基本方法(零件)的组装顺序,所有基本操作都已经实现。而工厂模式关注的是零件的创建。
- 建造者模式和模版方法模式
1.这两个模式解决问题的类型不一样,建造者模式是创建对象,模版方法是将实现推迟到子类中
2.如果建造者模式省掉导演类,那么builder构建方法就应该是模版方法。
7.参考
2.建造者模式