`
coolxing
  • 浏览: 870199 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
9a45b66b-c585-3a35-8680-2e466b75e3f8
Java Concurre...
浏览量:95995
社区版块
存档分类
最新评论

使用Builder模式创建对象

阅读更多

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

 

5
1
分享到:
评论
5 楼 lemon_gogogo 2015-04-29  
抄来抄去有意思么? 《effectivejava》
4 楼 heipacker 2013-10-12  
这个也太复杂了吧,想想就创建一个对象而已 值吗
3 楼 wangchangshuai0010 2012-03-09  
不错的防泄漏方法!
2 楼 coolxing 2012-03-09  
minjie0128 写道
顺便问下,为什么要建个内部类啊

这个Builder是专门用于创建Person对象的, 所以Builder类从属于Person类. 因此使用内部类可以清晰的表述这种从属关系.
使用"静态"内部类则是为了在不存在Person对象时创建Builder对象
1 楼 minjie0128 2012-03-09  
顺便问下,为什么要建个内部类啊

相关推荐

    设计模式 创建型模式 Builder模式(建造者)

    这些的算法和步骤是稳定的,而构成这个对象的子对象却经常由于需求改变而发生变化,此时我们可以选择使用Builder模式。尽管Builder模式相当容易让人误解,但我认为这几点应该是不会有错的。因此我个人认为Builder...

    C#面向对象设计模式纵横谈\4 创建型模式Builder生成器模式.zip

    在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第4节:创建型模式Builder生成器模式

    设计模式之创建模式Builder

    将一个复杂对象的构造与它的表示分离,使同样的构建 过程可以创建不同的表示,这样的设计模式被称为建造者模式。

    C#面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式)

    C#面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式) 体验课程

    Java设计中的Builder模式的介绍

    Builder模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 使用场景 相同的方法,不同的执行顺序,产生不同的事件结果 多个部件或零件,都可以装配到一个对象中,但产生的运行...

    Builder模式

    Builder模式:将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。当创建复杂对象的算法应该独立于改对象的组成部分以及他们的装配方式时。当构建过程必须允许被构造的对象有不同的表示时。

    C#视频-面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式)

    C#视频-面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式)

    C#面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式) (Level 300)

    C#面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式) (Level 300)

    C#面向对象设计模式纵横谈(视频与源码)

    C#面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式) C#面向对象设计模式纵横谈(5):Factory Method 工厂方法模式(创建型模式) C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式) C#面向...

    设计模式可复用面向对象软件的基础.zip

    3.2 Builder(生成器)—对象创建型 模式 63 3.3 Factory Method(工厂方法)— 对象创建型模式 70 3.4 Prototype(原型)—对象创建型 模式 87 3.5 Singleton(单件)—对象创建型 模式 84 3.6 创建型模式的讨论 89...

    设计模式整理(很全)

    设计模式之Builder 汽车由车轮 方向盘 发动机很多部件组成,同时,将这些部件组装成汽车也是一件复杂的工作,Builder模式就是将这两种情况分开进行。 设计模式之Prototype(原型) 用原型实例指定创建对象的种类,...

    利用Builder方式创建对象示例代码

    主要给大家介绍了关于利用Builder方式创建对象的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    设计模式:可复用面向对象软件的基础--详细书签版

    3.2 builder(生成器)—对象创建型 模式 63 3.3 factory method(工厂方法)— 对象创建型模式 70 3.4 prototype(原型)—对象创建型 模式 87 3.5 singleton(单件)—对象创建型 模式 84 3.6 创建型模式...

    Penglq#book-1#Builder模式1

    Builder模式模式介绍模式的定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。Android源码中的模式实现在Android源码

    Android中用Builder模式自定义Dialog的方法

    前言 我们开发人员在实际项目过程中遇到的需求是多种...我们都知道Android系统自身的对话框如AlertDialog就采用了Builder模式,因此可见Builder模式很适合用来构建Dialog对象。 下面话不多说了,上代码。 BaseDialog.

    JAVA设计模式23种

    汽车由车轮 方向盘 发动机很多部件组成,同时,将这些部件组装成汽车也是一件复杂的工作,Builder模式就是将这两 种情况分开进行。 设计模式之Prototype(原型) 用原型实例指定创建对象的种类,并且通过拷贝这些原型...

    东北大学设计模式实验3

    练习实现 Composite 模式,并且练习使用 Builder 模式创建和组装对象。

    建造者模式(Builder Pattern)原理图

    2. **逐步构建复杂对象**:使用建造者模式时,复杂对象是一步一步构建起来的。这意味着可以将构建过程分解成多个步骤,每个步骤负责创建一个复杂对象的一部分。 3. **提供统一的接口**:客户端(即使用该模式的代码...

    设计模式之创建型模式

    本次代码只提供了创建型模式的应用代码和说明,包括:Singleton 单件,Abstract Factory 抽象工厂,Builder 生成器,Factory Method 工厂方法。 Singleton模式解决的是实体对象个数的问题。除了Singleton...

    设计模式--可复用面向对象软件的基础

    3.2 BUILDER(生成器)——对象创建型模式 3.3 FACTORY METHOD(工厂方法)——对象创建型模式 3.4 PROTOTYPE(原型)——对象创建型模式 3.5 SINGLETON(单件)——对象创建型模式 第四章 结构型模式 4.1 ADAPTER...

Global site tag (gtag.js) - Google Analytics