重构以使用构建器模式或伸缩构造函数模式
根据《Effective Java 2ed》第 2 项
伸缩构造函数模式,在 您提供一个构造函数 仅需要参数,其他 有一个可选参数,a 第三个有两个可选参数, 等等,最终形成 具有所有可选的构造函数 参数。
应用此模式的类的构造函数的示例借自 When will you use the构建器模式?
代码集 1a
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean cheese, boolean pepperoni) { ... }
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }
大小是必需参数。 奶酪、意大利辣香肠和培根是可选参数。 假设我想提供如下所示的构造函数。
代码集1b
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean pepperoni) { ... }
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon, int price, int) { ... }
另一个例子是
代码集2
public AttributeKey(String key, Class<T> clazz)
public AttributeKey(String key, Class<T> clazz)
public AttributeKey(String key, Class<T> clazz, @Nullable T defaultValue, boolean isNullValueAllowed)
public AttributeKey(String key, Class<T> clazz, @Nullable T defaultValue, boolean isNullValueAllowed, @Nullable ResourceBundleUtil labels)
我给出的两个最新示例没有遵循伸缩构造函数的特性< /strong> 作为代码集 1a 所做的
- 代码集 1b 和 2 是否包含在伸缩构造函数中?如果不是,它叫什么?
- 与使用 Builder 模式相比,哪一种(Builder 模式和代码集 1a,2 模式之间)提供更多好处
According to Effective Java 2ed Item 2
telescoping constructor pattern, in
which you provide a constructor with
only the required parameters, another
with a single optional parameter, a
third with two optional parameters,
and so on, culminating in a
constructor with all the optional
parameters.
An example of constructors of the class applying this pattern is borrowed from When would you use the Builder Pattern?
code set 1a
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean cheese, boolean pepperoni) { ... }
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }
size is a required parameter.
cheese, pepperoni, and bacon are optional parameters.
Supposing that I would like to provide the constructor like below.
code set 1b
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean pepperoni) { ... }
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon, int price, int) { ... }
Another example is that
code set 2
public AttributeKey(String key, Class<T> clazz)
public AttributeKey(String key, Class<T> clazz)
public AttributeKey(String key, Class<T> clazz, @Nullable T defaultValue, boolean isNullValueAllowed)
public AttributeKey(String key, Class<T> clazz, @Nullable T defaultValue, boolean isNullValueAllowed, @Nullable ResourceBundleUtil labels)
The two latest example I gave didn't follow the characteristic of telescoping constructor as code set 1a did
- Are code set 1b and 2 included in telescoping constructor? if not, what is it called?
- Comparing to using Builder Pattern, which one (between Builder and pattern of code set 1a,2) provides more benefits
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这本身不是一种设计模式,而是一种称为构造函数链的编程技术。
同样的问题: 何时你使用了你借用的构建器模式吗?也很好地解释了其中的区别。简而言之,构建器优于构造函数链,因为它可能导致构造函数激增,从而变得难以维护。
希望有帮助。
This is not a design pattern per se, but it is a programming technique called constructor chaining.
The same SO question: When would you use the Builder Pattern? that you have borrowed also explains the difference nicely. In short, builder is preferred over constructor chaining as it can result in proliferation of constructors which can become hard to maintain.
Hope that helps.
在这种情况下,我会选择构建器或不同的机制,调用者可以在其中传递浇头集合。如果您需要验证允许使用哪些浇头,可以在构造函数或浇头设置器中执行此操作。伸缩/链接构造函数方法可能需要您将来添加额外的构造函数来处理额外的配料组合,而集合方法将自动处理任何场景。我还会避免在披萨类中为不同类型的配料提供特定的属性。如果您需要处理额外的奶酪怎么办?单个
cheese
布尔值无法处理该问题。Topping
类可以是具有子类的成熟对象,也可以仅用字符串替换它。In this case, I would go for either the builder or a different mechanism where the caller can pass a collection of toppings. If you need to validate what toppings are allowed, you can do that in the constructor or the Toppings setter. The telescoping/chaining constructor approach may require you to add additional constructors in the future to handle additional combinations of toppings, whereas a collection approach will handle any scenario automatically. I would also avoid having specific properties in the pizza class for different types of toppings. What if you need to handle extra cheese? A single
cheese
boolean will not handle that. TheTopping
class can be a full-fledged object with subclasses, or you could replace it with just a string.