当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

使用Builder模式创建对象

发表于: 2012-03-08   作者:coolxing   来源:转载   浏览:
摘要: [coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.] 创建对象的方法很多, 常见的有构造函数, 静态工厂方法, 工厂方法等.  以上三种方法不适合创建需要提供多个参数的对象, 而其中某些参数是可选的场景. 考虑一个Person类: public class Person { // 必须的参数 private int id; private

[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模式只适合创建对象时需要指定多个可选参数的场景.

 

使用Builder模式创建对象

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号