1.场景问题解决
1.1 场景描述
度假计划生成项目设计
度假计划的因素:时间、门票、餐厅、住宿、特殊活动等
一个计划就是一个具体对象,要便于扩展,可以一日游,三日游,七日游等
1.2 OO设计
1.3 需求变动
1.4 带来问题
2.用设计模式改进
2.1 分析
2.2 重新设计
[外链图片转存失败(img-86g1yhCE-1568389284434)(https://raw.githubusercontent.com/bobshute/public/master/imgs/csdn/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/16%E7%94%9F%E6%88%90%E5%99%A8%E6%A8%A1%E5%BC%8F-1.png)]
2.3 源码
- 基本对象(Vacation[假期],VacationDay[假期每天详细])
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
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) {
e.printStackTrace();
}
}
public void setStDate(String std) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
mStDate = sdf.parse(std);
} catch (ParseException e) {
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();
}
}
import java.util.ArrayList;
import java.util.Date;
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,Builder3d,Builder4d,BuilderSelf)
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;
}
}
public class Builder3d extends AbsBuilder {
public Builder3d(String std) {
super(std);
}
@Override
public void buildDay(int i) {
mVacation.setVacationDay(i);
}
@Override
public void addHotel(String hotel) {
mVacation.setHotel(hotel);
}
@Override
public void addTicket(String ticket) {
mVacation.addTicket(ticket);
}
@Override
public void addEvent(String event) {
mVacation.addEvent(event);
}
@Override
public void buildvacation() {
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);
}
@Override
public void buildDay(int i) {
mVacation.setVacationDay(i);
}
@Override
public void addHotel(String hotel) {
mVacation.setHotel(hotel);
}
@Override
public void addTicket(String ticket) {
mVacation.addTicket(ticket);
}
@Override
public void addEvent(String event) {
mVacation.addEvent(event);
}
@Override
public void buildvacation() {
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);
}
public BuilderSelf addDay() {
mVacation.addDay();
return this;
}
public BuilderSelf buildDay(int i) {
mVacation.setVacationDay(i);
return this;
}
public BuilderSelf addHotel(String hotel) {
mVacation.setHotel(hotel);
return this;
}
public BuilderSelf addTicket(String ticket) {
mVacation.addTicket(ticket);
return this;
}
public BuilderSelf addEvent(String event) {
mVacation.addEvent(event);
return this;
}
public Vacation getVacation() {
return mVacation;
}
}
- 指挥者((Director)和测试类(BuildermsTest)
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 BuildermsTest {
public static void main(String[] args) {
test3d();
test4d();
testself();
}
public static void test3d(){
Director mDirector = new Director(new Builder3d("2015-8-30"));
//mDirector.setBuilder(new Builder4d("2015-8-30"));
mDirector.construct();
}
public static void test4d(){
Director mDirector = new Director(new Builder4d("2015-12-29"));
mDirector.construct();
}
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.设计模式总结
3.1 定义
生成器模式:封装一个复杂对象构造过程,并允许按步骤构造。
生成器模式是一种创建型设计模式,它把对象的创建步骤抽象成生成器,并且可以通过指导类(director)对所有生成步骤的先后顺序进行控制。客户端使用指导类并传入相应的生成器,通过指导类的接口便可以得到相应的对象。
3.2 分析思路
[外链图片转存失败(img-ECk3ETrj-1568389284436)(https://raw.githubusercontent.com/bobshute/public/master/imgs/csdn/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/16%E7%94%9F%E6%88%90%E5%99%A8%E6%A8%A1%E5%BC%8F-2.png)]
- (1)产品(Product):具体生产器要构造的复杂对象;
- (2)抽象生成器(Bulider):抽象生成器是一个接口,该接口除了为创建一个Product对象的各个组件定义了若干个方法之外,还要定义返回Product对象的方法;
- (3)具体生产器(ConcreteProduct):实现Builder接口的类,具体生成器将实现Builder接口所定义的方法;
- (4)指挥者(Director):指挥者是一个类,该类需要含有Builder接口声明的变量。指挥者的职责是负责向用户提供具体生成器,即指挥者将请求具体生成器类来构造用户所需要的Product对象,如果所请求的具体生成器成功地构造出Product对象,指挥者就可以让该具体生产器返回所构造的Product对象。
3.3 两种演化形式
- 省略抽象生成器类
- 省略指导者类
4. 设计模式使用场景及注意
4.1 生成器优点
- 将复杂对象的创建过程封装起来
- 允许对象通过几个步骤来创建,并且可以改变过程(工厂模式只有一个步骤)
- 只需指定具体生成器就能生成特定对象,隐藏类的内部结构
- 对象的实现可以被替换
4.2 生成器模式与抽象工厂的差异
生成器模式和抽象工厂模式在功能上很相似,主要区别:
- 生成器一般用来创建大的复杂的对象
- 生成器模式强调的是一步步创建对象,可以改变步骤来生成不同的对象
- 一般来说生成器模式中对象不直接返回
5.参考文章
内容总计于HeadFirst设计模式及相关视频
设计模式学习笔记(十二:生成器模式)