使用Builder模式创建对象_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 使用Builder模式创建对象

使用Builder模式创建对象

 2012/3/14 9:58:42  coolxing  程序员俱乐部  我要评论(0)
  • 摘要:[coolxing按:转载请注明作者和出处,如有谬误,欢迎在评论中指正.]创建对象的方法很多,常见的有构造函数,静态工厂方法,工厂方法等.以上三种方法不适合创建需要提供多个参数的对象,而其中某些参数是可选的场景.考虑一个Person类:publicclassPerson{//必须的参数privateintid;privateStringname;privateintage;//可选参数privateStringcity;privateStringhoby;privateStringjob
  • 标签:创建 使用 模式 创建对象

[coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.]

创建对象的方法很多, 常见的有构造函数, 静态工厂方法, 工厂方法等.?

以上三种方法不适合创建需要提供多个参数的对象, 而其中某些参数是可选的场景.

考虑一个Person类:

public class Person {
	// 必须的参数
	private int id;
	private String name;
	private int age;
	
	// 可选参数
	private String city;
	private String hoby;
	private String job;
	private String sex;
}
??

如果给这个Person类提供合适的构造函数, 应该怎么做呢?

也许我们可以提供多个构造函数, 每个构造函数都包含必须的参数, 以及0个或多个可选参数. 例如:

public Person(int pid, String name, int age) {
		this.id = pid;
		this.name = name;
		this.age = age;
}
	
public Person(int id, String name, int age, String city) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.city = city;
}
	
public Person(int id, String name, int age, String city, String hoby) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.city = city;
		this.hoby = hoby;
}
	
public Person(int id, String name, int age, String city, String hoby, String job) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.city = city;
		this.hoby = hoby;
		this.job = job;
}

public Person(int id, String name, int age, String city, String hoby, String job, String sex) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.city = city;
		this.hoby = hoby;
		this.job = job;
		this.sex = sex;
}

这种方法至少存在这样的问题:

1. 如果需要创建一个只指定city和sex的Person对象, 我们就必须调用public Person(int id, String name, int age, String city, String hoby, String job, String sex)方法, 然后将hoby, job都赋值为空字符串. 这是让人疑惑的, 也是丑陋的.

2. 这样的代码难以阅读, 而且臃肿不堪, 不具备良好的可伸缩性.

?

当然我们可以同时提供属性的getter和setter方法, 然后只保留Person(int pid, String name, int age)一个构造函数.

如此的话, 我们先通过Person(int pid, String name, int age)方法创建Person对象, 然后调用需要的setter方法给可选参数赋值.

这是不错的解决方法, 但是创建对象被分成了几个步骤, 这会带来问题: 如果一不小心可能会让将尚未完全创建的Person对象泄露出去--结果是严重的.?

?

Builder设计模式就非常适合这样的场景:

public class Person {
	// 必须的参数
	private int id;
	private String name;
	private int age;

	// 可选参数
	private String city;
	private String hoby;
	private String job;
	private String sex;

	// 私有构造函数
	private Person(Builder builder) {
		this.id = builder.id;
		this.name = builder.name;
		this.age = builder.age;
		this.city = builder.city;
		this.hoby = builder.hoby;
		this.job = builder.job;
		this.sex = builder.sex;
	}

	public static class Builder {
		// 必须的参数
		private int id;
		private String name;
		private int age;

		// 可选参数
		private String city;
		private String hoby;
		private String job;
		private String sex;

		// 设置必须的参数
		public Builder(int id, String name, int age) {
			this.id = id;
			this.name = name;
			this.age = age;
		}
		
		// 设置可选参数, 返回Builder对象可以让调用者使用级联
		public Builder setCity(String city) {
			this.city = city;
			return this;
		}
		
		public Builder setHoby(String hoby) {
			this.hoby = hoby;
			return this;
		}
		
		public Builder setJob (String job) {
			this.job = job;
			return this;
		}
		
		public Builder setSex(String sex) {
			this.sex = sex;
			return this;
		}
		
		public Person build() {
			return new Person(this);
		}
	}
}

如果需要一个指定city和sex的Person对象, 就可以这样创建:

Person.Builder builder = new Person.Builder(1, "xing", 25);
Person person = builder.setCity("beijing").setSex().build();

在调用build方法完成之前, Person对象都没有被创建, 所以无需担心提前泄露的问题, 而且使用级联的方式使得代码简洁优雅.

?

总结: Builder模式只适合创建对象时需要指定多个可选参数的场景.

?

发表评论
用户名: 匿名