重构以使用构建器模式或伸缩构造函数模式

发布于 2024-10-31 07:29:22 字数 1573 浏览 4 评论 0原文

根据《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 所做的

  1. 代码集 1b 和 2 是否包含在伸缩构造函数中?如果不是,它叫什么?
  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

  1. Are code set 1b and 2 included in telescoping constructor? if not, what is it called?
  2. Comparing to using Builder Pattern, which one (between Builder and pattern of code set 1a,2) provides more benefits

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

耳根太软 2024-11-07 07:29:22

这种构造函数参数模式叫什么?

这本身不是一种设计模式,而是一种称为构造函数链的编程技术。

与使用构建器模式相比,哪一个提供更多好处

同样的问题: 何时你使用了你借用的构建器模式吗?也很好地解释了其中的区别。简而言之,构建器优于构造函数链,因为它可能导致构造函数激增,从而变得难以维护。

希望有帮助。

What is this pattern of constructors'parameters called?

This is not a design pattern per se, but it is a programming technique called constructor chaining.

Comparing to using Builder Pattern, which one provides more benefits

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.

人事已非 2024-11-07 07:29:22

在这种情况下,我会选择构建器或不同的机制,调用者可以在其中传递浇头集合。如果您需要验证允许使用哪些浇头,可以在构造函数或浇头设置器中执行此操作。伸缩/链接构造函数方法可能需要您将来添加额外的构造函数来处理额外的配料组合,而集合方法将自动处理任何场景。我还会避免在披萨类中为不同类型的配料提供特定的属性。如果您需要处理额外的奶酪怎么办?单个 cheese 布尔值无法处理该问题。 Topping 类可以是具有子类的成熟对象,也可以仅用字符串替换它。

public class Pizza
{
    // setters don't have to be private...
    public int Size {get; private set;}
    private List<Topping> toppings {get; private set;}

    public Pizza(int size) : this(size, new List<Topping>()) // call the other ctor with an empty list of toppings
    {
    }

    public Pizza(int size, List<Topping> toppings)
    {
        Size = size;
        Toppings = toppings;
    }
}

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. The Topping class can be a full-fledged object with subclasses, or you could replace it with just a string.

public class Pizza
{
    // setters don't have to be private...
    public int Size {get; private set;}
    private List<Topping> toppings {get; private set;}

    public Pizza(int size) : this(size, new List<Topping>()) // call the other ctor with an empty list of toppings
    {
    }

    public Pizza(int size, List<Topping> toppings)
    {
        Size = size;
        Toppings = toppings;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文