小秋:我想到另一种办法了,我可以通过set和get方法来设置可选参数的。我直接上代码你看看
public class Cake { private int size; private String apple; private String banana; private String orange; private String mango; public Cake(int size) { this.size = size; } //通过set来添加材料 public void setApple(String apple) { this.apple = apple; } public void setBanana(String banana) { this.banana = banana; } public void setMango(String mango) { this.mango = mango; } public void setOrange(String orange) { this.orange = orange; } }此时的小秋有点得意….
帅地:挺不错,这种方法比刚才的好多了,又简洁。
此时如果要new一个apple+orange+mango的蛋糕的话,代码如下:
Cake cake = new Cake(30); cake.setApple("apple"); cake.setOrange("orange"); cake.setMange("mange"); 参数依赖检查问题帅地:这种方法也是有缺点,例如用构造器重载时一行代码就可以搞定了,现在要用四行代码。
小秋:反正我觉得这样很nice(得意中…)。
帅地:不过这样写有一个致命的缺点,假如那些属性之间存在依赖性的话,怎么办?例如Cake多了A,B两个属性,并且这两个属性之间存在依赖关系。如果你设置了属性A,但是没有设置属性B,那么这个Cake对象就会出问题。或者属性的先后顺序设置也可能会导致出现问题。对于这种情况,你在什么地方检查这种相互依赖的逻辑?
小秋:有点蒙蔽,不知所措….。
小秋:那你说怎么办?
静态内部类帅地:其实你已经做的相当不错了,不过我今天就教你另外一个办法,我们可以开放一个静态内部类专门用来与外界打交道,用来收集用户想要设置的属性并且做检查。直接上代码:
public class Cake { private int size; private String apple; private String banana; private String orange; private String mango; //private,让外面无法直接创建 private Cake(Builer builer) { this.size = builer.size; this.apple = builer.apple; ..... } //专门用来与外界打交道 public static class Builer { private int size; private String apple; private String banana; private String orange; private String mango; public void setSize(int size) { this.size = size; } //为了省点代码,其他的省略 public Cake build() { //检查参数之间的依赖关系是否正确 return new Cake(this); } ..... } }假如我要new一个apple+orange的Cake
Cake.Builer builer = new Cake.Builer(); builer.setSize(30); builer.setApple("apple"); builer.setOrange("orange"); //创建一个蛋糕 Cake cake = builer.build();帅地:这种方法牛吧?这还不够,我们还可以采用链式调用的方法。
链式调用 public class Cake { private int size; private String apple; private String banana; private String orange; private String mango; //private,让外面无法直接创建 private Cake(Builer builer) { this.size = builer.size; this.apple = builer.apple; ..... } //专门用来与外界打交道 public static class Builer { private int size; private String apple; private String banana; private String orange; private String mango; //返回参数改为Builer public Builer setSize(int size) { this.size = size; return this; } public Builer setApple(String apple) { this.apple = apple; return this; } //为了省点代码,其他的省略 public Cake build() { //检查参数之间的依赖关系是否正确 return new Cake(this); } } }如何使用?
Cake cake = new Cake.Builer() .setSize(30) .setApple("apple") .setOrange("orange") .build();一行代码就搞定了。
帅地:厉害吧?
小秋:涨知识了,看来我还是太年轻了,以后得好好向帅地学习。
建造者模式帅地:其实,上面那种方法算是23种设计模式中的其中一种—-建造者模式。不过这只是一个简化版的建造者模式。
对于建造者模式,具体的UML图是这样的:
在这个UML图中,Builder是一个接口,定义一套规范,而我们使用的例子中,没有使用接口,直接使用具体类,但核心思想还是一样的。
其核心思想就是:将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
小秋:哇,强啊。我要给你点赞…..
算是第二次采取对话的方式写….,以后会多采取这种方式来写勒。