来来来,今天说说建造者模式【构建我的午餐】
场景:公司午餐是自助餐,所以自己要吃什么菜的选择性是很大的
菜
- 鸡肉
- 鱼肉
- 猪肉
- 豆腐
- 菠菜
- 土豆
- 紫菜汤
- 米饭
接下来就要构造今天的午餐了,哈哈
package t2;
/**
* 建造者模式
* 以午餐为例吧
* 刚吃完,还有点撑,哈哈
* 场景:自助餐【公司就是吃这个】
*
*/
public class Lunch {
private final String chicken ;//鸡肉
private final String fish ;//鱼肉
private final String pork ;//猪肉
private final String doufu ;//豆腐
private final String spinage ;//菠菜
private final String potato ;//土豆
private final String seaweedSoup ;//紫菜汤
private final String rice ;//米饭
public Lunch(Builder builder) {
chicken = builder.chicken ;
fish = builder.fish ;
pork = builder.pork ;
doufu = builder.doufu ;
spinage = builder.spinage ;
potato = builder.potato ;
seaweedSoup = builder.seaweedSoup ;
rice = builder.rice ;
}
@Override
public String toString() {
return "Lunch [chicken=" + chicken + ", fish=" + fish + ", pork=" + pork + ", doufu=" + doufu + ", spinage="
+ spinage + ", potato=" + potato + ", seaweedSoup=" + seaweedSoup + ", rice=" + rice + "]";
}
public static class Builder{
private String chicken ;//鸡肉
private String fish ;//鱼肉
private String pork ;//猪肉
private String doufu ;//豆腐
private String spinage ;//菠菜
private String potato ;//土豆
private String seaweedSoup ;//紫菜汤
private String rice ;//米饭
public Builder chicken(String value){
chicken = value ;
return this ;
}
public Builder fish(String value){
fish = value ;
return this ;
}
public Builder pork(String value){
pork = value ;
return this ;
}
public Builder doufu(String value){
doufu = value ;
return this ;
}
public Builder spinage(String value){
spinage = value ;
return this ;
}
public Builder potato(String value){
potato = value ;
return this ;
}
public Builder seaweedSoup(String value){
seaweedSoup = value ;
return this ;
}
public Builder rice(String value){
rice = value ;
return this ;
}
public Lunch bulid() {
return new Lunch(this);
}
}
}
测试
package t2;
public class Test {
public static void main(String[] args) {
Lunch lunch = new Lunch.Builder()
.chicken("我爱吃鸡肉")
.fish("听说吃鱼会变聪明")
.rice("从小吃菜要拌米饭")
.spinage("妈妈说吃青菜对身体好")
.seaweedSoup("饭后一碗汤,啧啧")
.bulid();
System.out.println(lunch.toString());
}
}
结果
Lunch [chicken=我爱吃鸡肉, fish=听说吃鱼会变聪明, pork=null, doufu=null, spinage=妈妈说吃青菜对身体好, potato=null, seaweedSoup=饭后一碗汤,啧啧, rice=从小吃菜要拌米饭]
小结:摘自这位作者总结的不错
直接通过构造函数传参的方式设置属性,这种方法如果属性过多的话会让构造函数十分臃肿,而且不能灵活的选择只设置某些参数。
采用重叠构造区模式,先写第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个构造器有两个可选参数,以此类推;如果参数比较多时,类里面会出现一堆构造方法,并且阅读困难,很容易就把两个属性参数写颠倒位置了,编译不会出错,但运行就会出错了
采用Javabean 的写法,写一堆属性的setter方法,通过生成对象,让后调用setter方法给属性赋值。 这种方法有个劣势就是构造的过程被分到几个调用中,在构造中可能处于不一致状态,无法保证一致性。
采用Builder 模式构造对象,当一个类的参数多的情况下,使用重叠构造器模式客户端代码会很难编写,并且可读性差;使用javabean模式,调用一个无参的构造器,然后调用setter方法来设置每个必要的参数。但是javabean自身有着严重的缺点,因为构造过程被分到几个调用中,在构造javabean可能处于不一致的状态,类无法仅仅通过检验构造器参数的有效性来保证一致性。另一点不足之处,javabean模式阻止了把类做成不可变的可能,这就需要程序员付出额外的努力来确保他的线程安全; build模式 既能保证像重叠构造器那样的安全,也能实现JavaBean模式那样的可读性。
~结束~