生成器模式(9)

生成器模式(Builder Pattern)

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示。
生成器模式:封装一个复杂对象构造过程,并允许按步骤构造。

何时使用:

  • 当系统准备为用户提供一个内部结构复杂的对象,而且在构造方法中编写创建该对象的代码无法满足用户需求时,就可以使用生成器模式老构造这样的对象。
  • 当某些系统要求对象的构造过程必须独立于创建该对象的类时。

优点:

  • 生成器模式将对象的构造过程封装在具体的生成器中,用户使用不同的具体生成器就可以得到该对象的不同表示。
  • 生成器模式将对象的构造过程从创建该对象的类中分离出来,使用户无须了解该对象的具体组件。
  • 可以更加精细有效的控制对象的构造过程。将对象的构造过程分解成若干步骤,这就是程序可以更加精细,有效的控制整个对象的构造。
  • 生成器模式将对象的构造过程与创建该对象类解耦,是对象的创建更加灵活有弹性。
  • 当增加新的具体的生成器是,不必修改指挥者的代码,即该模式满足开-闭原则。

模式的重心在于分离构建算法和具体的构造实现,从而使构建算法可以重用。

比如我们要得到一个日期,可以有不同的格式,然后我们就使用不同的生成器来实现。

优点:
将复杂对象的创建过程封装起来
允许对象通过几个步骤来创建,并且可以改变过程(工厂模式只有一个步骤)
只需指定具体生成器就能生成特定对象,隐藏类的内部结构
对象的实现可以被替换

生成器模式和抽象工厂模式在功能上很相似,主要区别:
生成器一般用来创建大的复杂的对象
生成器模式强调的是一步步创建对象,可以改变步骤来生成不同的对象
一般来说生成器模式中对象不直接返回

首先是这个类(产品):

public class MyDate {
	public String date;
}

然后就是抽象生成器,描述生成器的行为:

public interface IDateBuilder {
   IDateBuilder buildDate(int y,int m,int d);
   String date();
}

接下来是具体生成器,一个以“-”分割年月日,另一个使用空格:

//具体生成器
public class DateBuilder1 implements IDateBuilder {
   private MyDate myDate;

   public DateBuilder1(MyDate myDate) {
   	this.myDate = myDate;
   }

   @Override
   public IDateBuilder buildDate(int y, int m, int d) {
   	myDate.date = y + "-" + m + "-" + d;
   	return this;
   }

   @Override
   public String date() {
   	return myDate.date;
   }
}

public class DateBuilder2 implements IDateBuilder {
   private MyDate myDate;

   public DateBuilder2(MyDate myDate) {
   	this.myDate = myDate;
   }

   @Override
   public IDateBuilder buildDate(int y, int m, int d) {
   	myDate.date = y + " " + m + " " + d;
   	return this;
   }

   @Override
   public String date() {
   	return myDate.date;
   }
}

接下来是指挥官,向用户提供具体的生成器:

//指挥者
public class Derector {
	private IDateBuilder builder;

	public Derector(IDateBuilder builder) {
		this.builder = builder;
	}

	public String getDate(int y, int m, int d) {
		builder.buildDate(y, m, d);
		return builder.date();
	}
}

使用如下:

public class TestUse {
	public static void main(String[] args) {
		MyDate date = new MyDate();
		IDateBuilder builder;
		
		builder = new DateBuilder1(date).buildDate(2066, 3, 5);
		System.out.println(builder.date());
		builder = new DateBuilder2(date).buildDate(2066, 3, 5);
		System.out.println(builder.date());
		
		Derector dc = new Derector(new DateBuilder1(date));
		System.out.println(dc.getDate(2066, 3, 5));
	}
}

使用不同生成器,可以使原有产品表现得有点不一样。
往往在实际的应用中,生成器要做的工作不会这么简单,而是相对复杂的(因为其产品一般是比较复杂的),原有构建的维护会转移到生成器的维护上。

builder 设计模式的使用场景

1.基本对象

@Data
@ToString
public class User {

	private  String firstName; // required
	private  String lastName; // required
	private  int age; // optional
	private  String phone; // optional
	private  String address; // optional
	
	public User(UserBuilder builder) {
		this.firstName = builder.firstName;
		this.lastName=builder.lastName ;
		this.age=builder.age;
		this.phone=builder.phone;
		this.address=builder.address;
	}
	
	public static class UserBuilder{
		private final String firstName; // required
		private  String lastName; // required
		private  int age; // optional
		private  String phone; // optional
		private  String address; // optional
		
		public UserBuilder(String firstName) {
			super();
			this.firstName = firstName;
		}
		public UserBuilder excuteLastName(String lastName){
			this.lastName = lastName;
			return this;
		}
		public UserBuilder excuteAge(int age){
			this.age = age;
			return this;
		}
		public UserBuilder excutePhone(String phone){
			this.phone = phone;
			return this;
		}
		public UserBuilder excuteAddress(String address){
			this.address = address;
			return this;
		}		
		public User getUser(){
			return new User(this);
		}		
	}	
}

测试:

public User getUser(){
	return  new User.UserBuilder("aa").excuteAddress("addr")
	.excuteAge(12).excutePhone("123").getUser();
}

2.Map 的进一步封装,使得支持链式

public class SelfMap{
	private Map<String,Object> map = new HashMap<String,Object>();
	public SelfMap() {
		
	}
	public SelfMap addVal(String key,Object value){
		map.put(key, value);
		return this;
	}
	public SelfMap removeVal(String key){
		if(map.keySet().contains(key)){
			map.remove(key);
		}
		return this;
	}	
	public Object getVal(String key){
		if(map.keySet().contains(key)){
			return map.get(key);
		}
		return null;
	}
	public Map<String, Object> builder() {
		return map;
	}	
}

测试:

SelfMap map =  new SelfMap().addVal("aa", "123456")
				.addVal("bb", "56");
map.addVal("f", "44").removeVal("dfg").removeVal("aa");
Object obj = map.getVal("bb");
System.out.println(obj);

3.综合实例
在这里插入图片描述

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 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();
	}
}
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 block
			e.printStackTrace();
		}
	}

	public void addDay() {
		mVacationDay = new VacationDay(nextDate(mDays));
		mVacationDayLst.add(mVacationDay);
		mDays++;
	}
	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();
	}
}

builder 实现

public abstract class AbsBuilder {

	public Vacation mVacation;

	public AbsBuilder(String std) {
		mVacation = new Vacation(std);
	}

	public abstract void buildvacation();

	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 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");
		addTicket("Theme Park  qq");
		addHotel("Four Seasons");

		mVacation.addDay();

		addTicket("Plane Ticket");
		addEvent("City Tour");
		addEvent("Fly to Home");

	}
}

Director 实现

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();
	}
}

测试:

Director mDirector = new Director(new Builder4d("2015-12-29"));
mDirector.construct();

可以改造一下:

public class BuilderSelf {
	public Vacation mVacation;

	public BuilderSelf(String std) {
		mVacation = new Vacation(std); 
	}

	public BuilderSelf addDay() { 
		mVacation.addDay();
		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;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值