- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
回到 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();
}
}
现在我的“改进”版本:
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();
}
}
正如您在我的“改进版本”中看到的那样,我们需要添加有关任何附加属性(或选项,在本例中)的代码的地方减少了 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();
}
}
最佳答案
(我期待这个问题被迁移,但无论如何我都会回答 - 答案将被保留。)
你声称这个类仍然是不可变的......但我不认为它是。
Options.Builder builder = new Options.Builder().option1("foo").option2(1);
Options options = builder.build();
builder.option1("changed");
System.out.println(options.getOption1());
请注意,通过一些修改来防止这种情况(在 build()
方法中将 options
设置为 null
以便构建器不能重用)这基本上是 Protocol Buffers 的 Java 实现的模式习惯使用。我相信它现在使用的东西更接近于 Josh 早期的模式。
关于java - 对 Joshua Bloch 的 Builder 设计模式的改进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6388696/
在“Effective Java”一书中,Joshua Bloch 说:“不可能在 Collection Framework 中子类化任何方便的实现类”。 如果 ArrayList、LinkedLis
从这里Artima article on clone vs copy constructor : Object's clone method is very tricky. It's based on
我的一个类中有许多构造函数,因此我认为为其中一个类(Spring 项目)实现 Bloch 的“构建器模式”(参见 http://www.informit.com/articles/article.as
假设我有一个抽象类 (BaseThing)。它有一个必需参数(“base required”)和一个可选参数(“base optional”)。我有一个扩展它的具体类(Thing)。它还具有一个必需参
我正在考虑使用 Joshua Bloch 所描述的构建器模式 here .我有一个显示警报消息的类,将被许多应用程序使用。它可以有大量不同的选项,如 line1、btn txt、title、line2
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 8 年前。 Improve th
读了两遍这本书的这一部分后,我仍然不明白为什么如此广泛地阐述这一点。非静态成员类是语言的一部分。同意并非任何编程语言的所有部分都是完美的。发挥非静态成员类的优点,即可以访问封闭实例的方法,因此很少会超
我正在阅读 Joshua Bloch 的书 effective java。在“favor composition over inheritance”的第 16 条中,他给出了一个使用 HashSet
我正在使用 QuTiP 绘制 Bloch 球体图。我想给它一个标题。我怎样才能做到这一点?我在 Google 上搜索但找不到答案。 最佳答案 您需要将 Bloch 球体渲染到 matploltib 中
我想知道封闭类可以创建多少个静态成员类实例。我假设只有一个,但 Bloch 的以下摘录对我来说没有意义。 引用 Joshua Bloch 的 Effective Java - Item 22*:优先使
我使用 Joshua Bloch 介绍的 Java 构建器模式。有时,我发现与原始类型相比,使用默认值初始化某些字段的开销更高。 因此,我的策略是什么。 我延迟了这些字段的默认值初始化操作。 在构建过
考虑 Bloch 的 Builder 模式的逐字副本(对 C# 的语法进行了更改): public class NutritionFacts { public int ServingSize {
与仅使用构造函数创建对象相比,内存和性能使用情况如何? 这里的用法是创建一个 Set或 List可能包含数以百万计的条目,我担心使用 Bloch 的 Builder 模式的开销。我过去使用过它,但从未
我最近开始使用 QuTip for Python。我想使用 qutip.Bloch() 绘制 Bloch 球体中两级系统的演化,但我不知道如何将这样的图绘制为连续线。 这是我目前使用的代码: bola
这个问题已经有答案了: Properly removing an Integer from a List (8 个回答) 已关闭 9 年前。 我现在正在阅读 Joshua Bloch 的《Effect
Joshua Bloch 建议将构建器模式作为具有太多构造选项或太多构造函数参数的类的解决方案。 GOF builder 的基本意图是“将对象的构造与其表示分离”,或者基本上是为具有相同基类的不同最终
我正在尝试为下面的类使用 Builder 模式。最初我使用类的构造函数来设置所有参数,但不小心遇到了 Builder 模式,它看起来很适合我的用例。 下面是我的类(class),其中人们通常总是传递
回到 2007 年,我读了一篇关于 Joshua Blochs 的文章,介绍了“构建器模式”以及如何修改它以改善构造函数和 setter 的过度使用,尤其是当一个对象具有大量属性时,其中大部分是可选的
请看这个link .关于枚举,Bloch 先生说 Java’s enum types are classes that export one instance for each enumeration
我加入了 C# 潮流,想知道是否有 Joshua Bloch 的 Effective Java 的等价物对于 C# 世界。 鉴于它们的相似性,我已经能够将一些 Java 知识应用到 C# 中,但我对最
我是一名优秀的程序员,十分优秀!