重构使用Builder模式或Telescoping构造函数模式 [英] Refactor to use Builder pattern or Telescoping constructor pattern

查看:168
本文介绍了重构使用Builder模式或Telescoping构造函数模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Effective Java 2ed第2项


伸缩构造函数模式
中,你提供了一个构造函数
只有必需的参数,另一个
有一个可选参数,一个
第三个有两个可选参数
等等,最后是一个
构造函数,其中包含所有可选的
参数。


模式是从借用的。何时使用构建器模式?

代码集1a



  size} {...} 
披萨(int size,boolean cheese){...}
披萨(int size,boolean cheese,boolean pepperoni){...}
披萨int size,boolean cheese,boolean pepperoni,boolean bacon){...}

em> required 参数。
奶酪,意大利辣香肠和培根是可选参数。
假设我想提供如下的构造函数。



代码集1b

  Pizza(int size){...} 
Pizza(int size,boolean cheese){...} ,boolean pepperoni){...}
{...}

另一个例子是



代码集2 b
$ b

  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)

两个最新示例伸缩构造函数的特性作为代码集合1a


  1. 伸缩构造函数中是否包含代码集1b和2?

  2. 与使用Builder Pattern相比,哪一个(在Builder和代码集1a,2的模式之间)提供了更多的好处


解决方案

在这种情况下,我会去构建器或不同的机制,调用者可以传递一系列的配料。如果你需要验证哪些浇头是允许的,你可以在构造函数或浇头设置器中做。伸缩/链接构造函数方法可能需要你在将来添加额外的构造函数来处理额外的顶部组合,而集合方法将自动处理任何情况。我也会避免在比萨饼类中有不同类型的配料的特定属性。如果你需要处理额外的奶酪怎么办?单个 cheese 布尔将不处理。 顶部类可以是具有子类的完整对象,也可以只用一个字符串来替换它。

  public class Pizza 
{
// setters不必是私人的...
public int Size {get; private set;}
private List< Topping> toppings {get; private set;}

public Pizza(int size):this(size,new List< Topping>())//使用空列表调用另一个ctor
{
}

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


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

解决方案

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;
    }
}

这篇关于重构使用Builder模式或Telescoping构造函数模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆