建造者模式,12306购票例子演进
购票流程例子
- 普通买票需要输入出发地,目的地,日期即可
- 通过助手需要添加更多的信息
模型抽象
模拟三个场景
具体的代码实现
预计划订单
public class PlanOrder {
// 原搜索乘车日期
private Date date;
// 出发地
private String srcCity;
// 目的地
private String destCity;
// 乘车人,简化成string表示
private List<String> persons;
// 优先车次,简化成string表示
private List<String> priorityCarNumber;
// 优先席别
private List<String> priorityCarSeat;
// 等等..,举例说明,这里不再设置多余的字段
// 构造函数【普通购票,简单的输入日期和起始和目的地】
public PlanOrder(Date date, String srcCity, String destCity) {
this.date = date;
this.srcCity = srcCity;
this.destCity = destCity;
}
// 构造函数【复杂购票,简单的输入日期和起始和目的地】 + 【该乘客计划购买2人票, 且都是一等席位】
public PlanOrder(Date date, String srcCity, String destCity, List<String> persons, List<String> priorityCarSeat) {
this.date = date;
this.srcCity = srcCity;
this.destCity = destCity;
this.persons = persons;
this.priorityCarSeat = priorityCarSeat;
}
// 构造函数【定制购票,简单的输入日期和起始和目的地】 + 【该乘客计划1人票, 指定做G45次列车,二等席位】
public PlanOrder(Date date, String srcCity, String destCity, List<String> persons, List<String> priorityCarNumber,
List<String> priorityCarSeat) {
this.date = date;
this.srcCity = srcCity;
this.destCity = destCity;
this.persons = persons;
this.priorityCarNumber = priorityCarNumber;
this.priorityCarSeat = priorityCarSeat;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getSrcCity() {
return srcCity;
}
public void setSrcCity(String srcCity) {
this.srcCity = srcCity;
}
public String getDestCity() {
return destCity;
}
public void setDestCity(String destCity) {
this.destCity = destCity;
}
public List<String> getPersons() {
return persons;
}
public void setPersons(List<String> persons) {
this.persons = persons;
}
public List<String> getPriorityCarNumber() {
return priorityCarNumber;
}
public void setPriorityCarNumber(List<String> priorityCarNumber) {
this.priorityCarNumber = priorityCarNumber;
}
public List<String> getPriorityCarSeat() {
return priorityCarSeat;
}
public void setPriorityCarSeat(List<String> priorityCarSeat) {
this.priorityCarSeat = priorityCarSeat;
}
@Override
public String toString() {
return "PlanOrder [date=" + date + ", srcCity=" + srcCity + ", destCity=" + destCity + ", persons=" + persons
+ ", priorityCarNumber=" + priorityCarNumber + ", priorityCarSeat=" + priorityCarSeat + "]";
}
}
封装client测试类
public class NormalClient {
public static void main(String[] args) {
// 构造函数【普通购票,简单的输入日期和起始和目的地】
PlanOrder planOrder = new PlanOrder(new Date(), "上海东", "北京西");
System.out.println(planOrder);
// 构造函数【复杂购票,简单的输入日期和起始和目的地】 + 【该乘客计划购买2人票, 且都是一等席位】
PlanOrder planOrder2 = new PlanOrder(new Date(), "广州南", "重庆西", Arrays.asList("张三", "小王"), Arrays.asList("一等座"));
System.out.println(planOrder2);
// 构造函数【定制购票,简单的输入日期和起始和目的地】 + 【该乘客计划1人票, 指定做G45次列车,二等席位】
PlanOrder planOrder3 = new PlanOrder(new Date(), "武汉站", "兰州", Arrays.asList("小丽"), Arrays.asList("二等座"), Arrays.asList("G45"));
System.out.println(planOrder3);
// ?? 问题分析,12306订票的人需求都不一致,那得写多少个构造函数啊 ??
}
}
测试结果
PlanOrder [date=Fri Jan 18 15:50:24 CST 2019, srcCity=上海东, destCity=北京西, persons=null, priorityCarNumber=null, priorityCarSeat=null]
PlanOrder [date=Fri Jan 18 15:50:24 CST 2019, srcCity=广州南, destCity=重庆西, persons=[张三, 小王], priorityCarNumber=null, priorityCarSeat=[一等座]]
PlanOrder [date=Fri Jan 18 15:50:24 CST 2019, srcCity=武汉站, destCity=兰州, persons=[小丽], priorityCarNumber=[二等座], priorityCarSeat=[G45]]
?? 问题分析,12306订票的人需求都不一致,那得写多少个构造函数啊 ??
改进,建造者模式方式bulider
具体的代码实现
预计划订单,这里更名为PlanOrder2 作为区别
public class PlanOrder2 {
// 原搜索乘车日期
private Date date;
// 出发地
private String srcCity;
// 目的地
private String destCity;
// 乘车人,简化成string表示
private List<String> persons = new ArrayList<>(5);
// 优先车次,简化成string表示
private List<String> priorityCarNumber = new ArrayList<>(5);
// 优先席别
private List<String> priorityCarSeat = new ArrayList<>(5);
// 等等..,举例说明,这里不再设置多余的字段
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getSrcCity() {
return srcCity;
}
public void setSrcCity(String srcCity) {
this.srcCity = srcCity;
}
public String getDestCity() {
return destCity;
}
public void setDestCity(String destCity) {
this.destCity = destCity;
}
public List<String> getPersons() {
return persons;
}
public void setPersons(List<String> persons) {
this.persons = persons;
}
public List<String> getPriorityCarNumber() {
return priorityCarNumber;
}
public void setPriorityCarNumber(List<String> priorityCarNumber) {
this.priorityCarNumber = priorityCarNumber;
}
public List<String> getPriorityCarSeat() {
return priorityCarSeat;
}
public void setPriorityCarSeat(List<String> priorityCarSeat) {
this.priorityCarSeat = priorityCarSeat;
}
@Override
public String toString() {
return "PlanOrder [date=" + date + ", srcCity=" + srcCity + ", destCity=" + destCity + ", persons=" + persons
+ ", priorityCarNumber=" + priorityCarNumber + ", priorityCarSeat=" + priorityCarSeat + "]";
}
}
建造者
public interface TicketBulider {
void bulidDate(Date date);
void bulidSrcCity(String srcCity);
void bulidDestCity(String destCity);
void bulidPerson(String person);
void bulidPriorityCarNumber(String priorityCarNumber);
void bulidPriorityCarSeat(String priorityCarSeat);
PlanOrder2 build();
}
/**
* 特殊说明:这个的bulidXXX方法只是简单赋值,实际开发中会有很多逻辑
*
* @author it
*/
public class TicketBuliderImpl implements TicketBulider {
private PlanOrder2 planOrder = new PlanOrder2();
@Override
public void bulidDate(Date date) {
planOrder.setDate(date);
}
@Override
public void bulidSrcCity(String srcCity) {
planOrder.setSrcCity(srcCity);
}
@Override
public void bulidDestCity(String destCity) {
planOrder.setDestCity(destCity);
}
@Override
public void bulidPerson(String person) {
planOrder.getPersons().add(person);
}
@Override
public void bulidPriorityCarNumber(String priorityCarNumber) {
planOrder.getPriorityCarNumber().add(priorityCarNumber);
}
@Override
public void bulidPriorityCarSeat(String priorityCarSeat) {
planOrder.getPriorityCarSeat().add(priorityCarSeat);
}
@Override
public PlanOrder2 build() {
// 构造的时候需要过程,如
// 乘车人: 区分成人、儿童、学生之间的差别
// 选择车次(最多选择5个车次)
// 选择车次(最多选择5个车次)
// 等..,这里不处理
return planOrder;
}
}
测试类BuliderClient
public class BuliderClient {
public static void main(String[] args) {
// 构造函数【普通购票,简单的输入日期和起始和目的地】
TicketBulider bulider = new TicketBuliderImpl();
bulider.bulidDate(new Date());
bulider.bulidSrcCity("上海东");
bulider.bulidDestCity("北京西");
PlanOrder2 planOrder = bulider.build();
System.out.println(planOrder);
// 构造函数【复杂购票,简单的输入日期和起始和目的地】 + 【该乘客计划购买2人票, 且都是一等席位】
TicketBulider bulider2 = new TicketBuliderImpl();
bulider2.bulidDate(new Date());
bulider2.bulidSrcCity("广州南");
bulider2.bulidDestCity("重庆西");
bulider2.bulidPerson("张三");
bulider2.bulidPerson("小王");
bulider2.bulidPriorityCarSeat("一等座");
PlanOrder2 planOrder2 = bulider2.build();
System.out.println(planOrder2);
// 构造函数【定制购票,简单的输入日期和起始和目的地】 + 【该乘客计划1人票, 指定做G45次列车,二等席位】
TicketBulider bulider3 = new TicketBuliderImpl();
bulider3.bulidDate(new Date());
bulider3.bulidSrcCity("武汉站");
bulider3.bulidDestCity("兰州");
bulider3.bulidPerson("小丽");
bulider3.bulidPriorityCarSeat("二等座");
bulider3.bulidPriorityCarNumber("G54");
PlanOrder2 planOrder3 = bulider3.build();
System.out.println(planOrder3);
// 解决问题
}
}
测试结果
PlanOrder [date=Fri Jan 18 16:00:07 CST 2019, srcCity=上海东, destCity=北京西, persons=[], priorityCarNumber=[], priorityCarSeat=[]]
PlanOrder [date=Fri Jan 18 16:00:07 CST 2019, srcCity=广州南, destCity=重庆西, persons=[张三, 小王], priorityCarNumber=[], priorityCarSeat=[一等座]]
PlanOrder [date=Fri Jan 18 16:00:07 CST 2019, srcCity=武汉站, destCity=兰州, persons=[小丽], priorityCarNumber=[G54], priorityCarSeat=[二等座]]
引入fluent风格继续优化
引入fluent风格
更改建造者
public interface TicketBulider2 {
TicketBulider2 bulidDate(Date date);
TicketBulider2 bulidSrcCity(String srcCity);
TicketBulider2 bulidDestCity(String destCity);
TicketBulider2 bulidPerson(String person);
TicketBulider2 bulidPriorityCarNumber(String priorityCarNumber);
TicketBulider2 bulidPriorityCarSeat(String priorityCarSeat);
PlanOrder2 build();
}
/**
* 特殊说明:这个的bulidXXX方法只是简单赋值,实际开发中会有很多逻辑
*
* @author it
*/
public class TicketBuliderImpl2 implements TicketBulider2 {
private PlanOrder2 planOrder = new PlanOrder2();
@Override
public TicketBulider2 bulidDate(Date date) {
planOrder.setDate(date);
return this;
}
@Override
public TicketBulider2 bulidSrcCity(String srcCity) {
planOrder.setSrcCity(srcCity);
return this;
}
@Override
public TicketBulider2 bulidDestCity(String destCity) {
planOrder.setDestCity(destCity);
return this;
}
@Override
public TicketBulider2 bulidPerson(String person) {
planOrder.getPersons().add(person);
return this;
}
@Override
public TicketBulider2 bulidPriorityCarNumber(String priorityCarNumber) {
planOrder.getPriorityCarNumber().add(priorityCarNumber);
return this;
}
@Override
public TicketBulider2 bulidPriorityCarSeat(String priorityCarSeat) {
planOrder.getPriorityCarSeat().add(priorityCarSeat);
return this;
}
@Override
public PlanOrder2 build() {
// 构造的时候需要过程,如
// 乘车人: 区分成人、儿童、学生之间的差别
// 选择车次(最多选择5个车次)
// 选择车次(最多选择5个车次)
// 等..,这里不处理
return planOrder;
}
}
测试FluentClient
public class FluentClient {
public static void main(String[] args) {
// 构造函数【普通购票,简单的输入日期和起始和目的地】
TicketBulider2 bulider = new TicketBuliderImpl2();
bulider.bulidDate(new Date()).bulidSrcCity("上海东").bulidDestCity("北京西");
PlanOrder2 planOrder = bulider.build();
System.out.println(planOrder);
// 构造函数【复杂购票,简单的输入日期和起始和目的地】 + 【该乘客计划购买2人票, 且都是一等席位】
TicketBulider2 bulider2 = new TicketBuliderImpl2();
bulider2.bulidDate(new Date()).bulidSrcCity("广州南").bulidDestCity("重庆西")
.bulidPerson("张三").bulidPerson("小王").bulidPriorityCarSeat("一等座");
PlanOrder2 planOrder2 = bulider2.build();
System.out.println(planOrder2);
// 构造函数【定制购票,简单的输入日期和起始和目的地】 + 【该乘客计划1人票, 指定做G45次列车,二等席位】
TicketBulider2 bulider3 = new TicketBuliderImpl2();
bulider3.bulidDate(new Date()).bulidSrcCity("武汉站").bulidDestCity("兰州")
.bulidPerson("小丽").bulidPriorityCarSeat("二等座").bulidPriorityCarNumber("G54");
PlanOrder2 planOrder3 = bulider3.build();
System.out.println(planOrder3);
}
}
这里不再测试,以满足大多数开源框架要求