设计模式之Builder模式

50 篇文章 11 订阅
2 篇文章 0 订阅

情景需要:

假设有这样一个Human类,要构造一个Human对象必须传递6个参数,其中前3个是必须的,后3个是可选的:

[java]  view plain copy print ?
  1. class Human {  
  2.   
  3.     // required parameters  
  4.     private final String name;  
  5.     private final String gender;  
  6.     private final int age;  
  7.   
  8.     // optional parameters  
  9.     private final int height;  
  10.     private final int weight;  
  11.     private final String country;  
  12. }  

那么,给这个类设计构造方法会是比较头疼的事。

一种方案是,我们可以设计一个有6个参数的构造方法,分别给name, gender, height, weight, country赋值,其中后3个值可以有缺省值。如:

[java]  view plain copy print ?
  1. public Human(String name, String gender, int age, int height = 180int weight = 50, String country = "China") {  
  2.     //... ...  
  3. }  

然而这样设计有一个不足之处,那就是后3个参数虽然有缺省值,但参数的顺序是固定的,不能变的,如果用户在传参的时候把顺序搞错了,就会产生错误。而且如果参数类型相同的话,编译器也不会报错。为了弥补这样的不足,我们可以重载构造方法,如:

[java]  view plain copy print ?
  1. public Human(String name, String gender, int age) {}  
  2.   
  3. public Human(int height) {} // 不能构成重载  
  4. public Human(int weight) {} // 不能构造重载  
  5. public Human(String country) {}  

这样虽然解决了参数顺序的问题,但如果这个类的可选参数有不只3个,比如有6个,10个,20个的话,那么就要设计大量的重载的方法,非常费事。而且上面的代码还存在一个问题,那就是第2个和第3个方法根本无法构成重载。也就是说,当可选参数的参数类型有重复的时候,上面的设计方法就不可行了。


这时候我们就可以采用 Builder模式 来解决这样问题。


Builder模式

我们可以在Human的内部定义一个静态的内部类Builder,通过这个类来完成对参数的赋值工作,如:
class Human {
	// required parameters
	private final String name;
	private final String male;
	private final int age;

	// optional parameters
	private final int height;
	private final int weight;
	private final String country;

	// builder class
	public static class Builder {
		// required parameters
		private final String name;
		private final String male;
		private final int age;

		// optional parameters
		private int height = 0;
		private int weight = 0;
		private String country = "none";

		public Builder(String name, String male, int age) {
			this.name = name;
			this.male = male;
			this.age = age;
		}

		public Builder setHeight(int h) {
			this.height = h;
			return this;
		}
		public Builder setWeight(int w) {
			this.weight = w;
			return this;
		}
		public Builder setCountry(String c) {
			this.country = c;
			return this;
		}

		public Human build() {
			return new Human(this);
		}
	}
}


然后为Human提供一个私有的构造方法,以Builder对象作为其形参,在此构造方法中完成参数的赋值:
[java]  view plain copy print ?
  1. private Human(Builder b) {  
  2.         name = b.name;  
  3.         gender = b.gender;  
  4.         age = b.age;  
  5.   
  6.         height = b.height;  
  7.         weight = b.weight;  
  8.         country = b.country;  
  9.     }  


这样一来,用户 在使用Human 这个类的时候,就可能以如下的方式来构造Human对象:

[java]  view plain copy print ?
  1. Human hm = new Human.Builder("bruce""male"20// 设置必须参数  
  2.             .setCountry("China"// 设置可选参数  
  3.             .setWeight(50// 设置可选参数  
  4.             .build(); // 构造对象  

显然,Human类的使用者在创建其对象时所写的代码就变得简单明了多了。


因此,当一个类的构造方法必须传递大量参数的时候,我们可以考虑使用Builder模式来构造此类。当应用程序对性能要求不是很高时,Builder模式是处理此类情形的最好方案。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值