9

所以我一直在阅读一些有效的 Java!书中最鼓舞人心的部分之一是不可变对象/构建器部分,布洛赫在其中写了“构建器”——类,而不仅仅是 POJO。

注意:我在这里谈论模型对象:例如ArticleCar

这就是我之前编写这些对象的方式:

public class Car {

     private String name;

     public void setName(String name) {
         this.name = name;
     }

     public String getName() {
         return name;
     }
}

现在你看到这个设计在很多方面都有缺陷,它需要可变性,你必须先用构造函数构造对象,然后设置名称。

当然,现在您可以将name字段设为 final 并将其用作构造函数中的参数,但是如果您有一个大对象包装例如许多 SQL - 表,那么您将有一个丑陋的构造函数,如下所示:

public Car(int horsepowers, String name, String brand, int yearManufactured,
    User owner, List<User> previousOwners) {
    //Set the values
}

这在创建对象时变得不可读,而这只是六个字段!

因此,布洛赫提出以下建议(具有不变性)

public class Car {

     public static class Builder {

         private String name;

         public Builder setName(String name) {
             this.name = name;
             return this;
         }

         public Car build() {
             reeturn new Car(this);
         }
     }

     private final String name;

     private Car(Builder builder) {
         name = builder.name;
     }

     public String getName() {
         return name;
     }
}

//Construction example
Car car = new Car.Builder().setName("Speedy").build();

现在这给了我们不变性!如果你有一些对象不是原始的或不可变的,只需将它们复制到Builder's 的 setter 中并再次将它们复制到Car's 的 getter 中。

但这很罗嗦,如果类足够小,我一直在使用构造函数参数。如果一个类需要一个可变字段,如果该类具有足够的属性(> 4 个),我只需使该字段可变。

另一个问题是,当使用 android 并且该类具有例如 aBitmap时,您必须返回实际的位图而不是复制它,因为这相当性能 - 昂贵。

我见过很多这样的问题,但我似乎无法在这个问题上找到一个好的答案:这些设计有什么标准吗?它们的设计如何?有什么好处/缺点?

提前致谢!

编辑:

问题是:

构造一个应该是不可变的对象模型的最佳方法是什么,并且 A)少量字段和 B)大量字段?如何处理上述Bitmap问题和类似问题?使某些字段可变?

抱歉含糊其辞。

4

3 回答 3

5

设计模式书是目前设计模式的阿尔法和欧米茄。然而,它并不新鲜,但似乎它通过了时间的考验。

您可以阅读每种设计模式的详细真实示例,它们如何相互关联,如何以及何时使用它们以及对每种设计模式的详尽解释。Builder 模式当然也包括在内。

至于回答你的问题,我可以提出我的观点,虽然它们当然不是权威的。

我认为,如果您有少量字段,则可以使用构造函数。如果您以checkstyle为例,它会触发超过 7 个参数的警告。

但是,如果您确定您将很快重构该类,或者您将不得不扩展它,我认为 Builder 模式更好,因为它更容易重构。重构构造函数从来都不是一件有趣的事。

如果您超过 7 个参数,我认为 Builder 会好得多。我一直在我正在广泛开展的当前项目中使用它。

请注意,通过使用构建器模式,您不会说“好吧,我是一个不可变的对象构建器”。你说“好的,我正在构建参数化对象”。因此,您的类中有一组可变字段不是问题。但是,如果您将类命名为ImmutableFooDTO,然后添加可变字段,则会导致混淆。

因此,如果有一组字段不能是可变的,那么将它们标记为 final 并使用构造函数/构建器并为可变字段提供设置器。

于 2013-05-09T09:07:32.237 回答
2

我将其输入为“答案”,因此我有空间进行解释,但这实际上只是对 Adam Aroid 发起的线程的评论。

Johan,首先我假设您在谈论有效 Java 中的第 2 条。

请注意,这里呈现的是一种 Builder 模式 Adam Aroid 提到的形式。Josh Bloch 在 Effective Java 中展示代码之前就直接提到了这一点:“它是 Builder 模式的一种形式 [Gamma95, p. 97]。” (那是在第 13 页。)他后来提到了一种使用另一种模式的方法(来自同一本书):“已设置参数的构建器制造了一个很好的抽象工厂 [Gamma95, p. 87]。

约翰,你问的问题对于这里的空间来说太宽泛了。我认为最好的答案是 Adam Aroid 的答案。这需要一些研究,然后应用该研究来获得一些经验。《设计模式》一书中的讨论极大地促进了这一点。我将投票支持亚当的答案。

于 2013-05-09T16:59:55.563 回答
-4

试试这个代码:

 public static boolean isEmailValid(String email) {

    boolean isValid = false;

    String expression = "^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";
    CharSequence inputStr = email;

    Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(inputStr);
    if (matcher.matches()) {
        isValid = true;
    }
    return isValid;
}
于 2016-06-08T15:04:34.113 回答