Jas*_*tos 3 java design-patterns
早在2007年,我读到了一篇关于Joshua Blochs对"构建器模式"的文章,以及如何修改它以改进构造函数和setter的过度使用,特别是当一个对象具有大量属性时,其中大多数是可选的.这里有一个关于这种设计模式的简短摘要[http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html].
我喜欢这个想法,并且从那时起就一直在使用它.它的问题,虽然从客户的角度来看它非常干净和漂亮,实现它可能是一个痛苦的屁股!对象中有许多不同的位置,其中单个属性是引用,因此创建对象,添加新属性需要花费大量时间.
所以......我有个主意.首先,Joshua Bloch风格的一个示例对象:
乔什布洛赫风格:
public class OptionsJoshBlochStyle {
private final String option1;
private final int option2;
// ...other options here <<<<
public String getOption1() {
return option1;
}
public int getOption2() {
return option2;
}
public static class Builder {
private String option1;
private int option2;
// other options here <<<<<
public Builder() {
}
public Builder option1(String option1) {
this.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.option2 = option2;
return this;
}
public OptionsJoshBlochStyle build() {
return new OptionsJoshBlochStyle(this);
}
}
private OptionsJoshBlochStyle(Builder builder) {
this.option1 = builder.option1;
this.option2 = builder.option2;
// other options here <<<<<<
}
public static void main(String[] args) {
OptionsJoshBlochStyle optionsVariation1 = new OptionsJoshBlochStyle.Builder().option1("firefox").option2(1).build();
OptionsJoshBlochStyle optionsVariation2 = new OptionsJoshBlochStyle.Builder().option1("chrome").option2(2).build();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我的"改进"版本:
public class Options {
private String option1;
private int option2;
// ...other options here
public String getOption1() {
return option1;
}
public int getOption2() {
return option2;
}
public static class Builder {
private final Options options;
public Builder() {
this.options = new Options();
}
public Builder option1(String option1) {
this.options.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.options.option2 = option2;
return this;
}
public Options build() {
return options;//new RequestContext(this);
}
}
private Options() {
}
public static void main(String[] args) {
Options optionsVariation1 = new Options.Builder().option1("firefox").option2(1).build();
Options optionsVariation2 = new Options.Builder().option1("chrome").option2(2).build();
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在"改进版本"中所看到的,我们需要添加关于任何添加属性(或者在这种情况下为选项)的代码的地方少了2个!我能看到的唯一不利因素是外部类的实例变量不能是最终的.但是,没有这个,这个班仍然是不可改变的.
这种可维护性的改进真的有任何不利因素吗?必须有一个原因,他重复了我没有看到的嵌套类中的属性?
PS:不确定这是否是StackOverflow的合适类型的问题,或者属于像[programmers.stackexchange.com]这样更主观的东西,所以我提前道歉!
编辑1:
@irreputable - Java中有这样的东西吗?由于这种变化,我仍然没有看到它如何变得线程安全.正如你的建议,我将不得不考虑安全发布.
public class OptionsDelegate {
private final OptionsData data;
private static class OptionsData {
String option1;
int option2;
}
// ...other options here
public String getOption1() {
return data.option1;
}
public int getOption2() {
return data.option2;
}
public static class Builder {
private OptionsData data;
public Builder() {
this.data = new OptionsData();
}
public Builder option1(String option1) {
this.data.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.data.option2 = option2;
return this;
}
public OptionsDelegate build() {
OptionsDelegate optionsDelegate = new OptionsDelegate(this.data);
this.data = null;
return optionsDelegate;
}
}
private OptionsDelegate(OptionsData data) {
this.data = data;
}
public static void main(String[] args) {
OptionsDelegate optionsVariation1 = new OptionsDelegate.Builder().option1("firefox").option2(1).build();
OptionsDelegate optionsVariation2 = new OptionsDelegate.Builder().option1("chrome").option2(2).build();
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 11
(我希望这个问题能够迁移,但无论如何我都会回答 - 答案会得到保留.)
你声称这个课程仍然是不可改变的...但我认为不是.
Options.Builder builder = new Options.Builder().option1("foo").option2(1);
Options options = builder.build();
builder.option1("changed");
System.out.println(options.getOption1());
Run Code Online (Sandbox Code Playgroud)
注意,有一个比特修改的,以防止这种(设置options到null在build()方法,以便构建器不能重新使用),这是基本上是Java实现的图案协议缓冲器用来使用.我相信它现在使用更接近Josh早期模式的东西.
| 归档时间: |
|
| 查看次数: |
3872 次 |
| 最近记录: |