设计模式16-生成器模式

312 阅读4分钟

1.场景问题解决

1.1 场景描述

度假计划生成项目设计 度假计划的因素:时间、门票、餐厅、住宿、特殊活动等
一个计划就是一个具体对象,要便于扩展,可以一日游,三日游,七日游等

1.2 OO设计

1.3 需求变动

1.4 带来问题

2.用设计模式改进

2.1 分析

2.2 重新设计

16生成器模式-1

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 分析思路

16生成器模式-2

  • (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设计模式及相关视频
设计模式学习笔记(十二:生成器模式)