面向对象的 JavaWorld : Getters/Setters vs Builder

标签 java oop design-patterns builder getter-setter

背景:

我找到了 this article在 JavaWorld 上,Allen Holub 解释了 Getters/Setters 的替代方法,该方法维护对象的实现应该被隐藏的原则(他的示例代码也可以在下面找到)。

据解释,类 Name/EmployeeId/Money 应该有一个采用单个字符串的构造函数 - 原因是如果你将其键入为 int,稍后需要将其更改为 long,您将不得不修改该类的所有用途,而使用此模式您无需必须。

问题一:

我在想:这不是简单地将问题转移到解析被抛来抛去的 String 参数上吗?例如,如果所有使用 EmployeeId 的代码(从 Exporter 接收)将 String 解析为 int , 突然你开始导出 long 值,你需要修改完全一样多的用途......如果你开始将它解析为 long 它可能必须改变到一个 double(即使这对 id 没有意义)...如果您不能确定将 String 解析成什么,您可以'执行任何操作

问题2:

除了这个问题,我还有另一个问题:我知道这篇文章已有七年多了,所以有人能给我指出一些最近关于 OO 设计的概述,特别是关于 getter/setter 和实现隐藏辩论的想法吗?

list 1. Employee:Builder 上下文


  public class Employee
  {   private Name        name;
      private EmployeeId  id;
      private Money       salary;

      public interface Exporter
      {   void addName    ( String name   );
          void addID      ( String id     );
          void addSalary  ( String salary );
      }

      public interface Importer
      {   String provideName();
          String provideID();
          String provideSalary();
          void   open();
          void   close();
      }

      public Employee( Importer builder )
      {   builder.open();
          this.name   = new Name      ( builder.provideName()     );
          this.id     = new EmployeeId( builder.provideID()       );
          this.salary = new Money     ( builder.provideSalary(),
                                    new Locale("en", "US") );
          builder.close();
      }

      public void export( Exporter builder )
      {   builder.addName  ( name.toString()   );
          builder.addID    ( id.toString()     );
          builder.addSalary( salary.toString() );
      }

      //...
  }

最佳答案

问题 1: 字符串解析似乎很奇怪。恕我直言,您只能做这么多来预测 future 的增强功能。您要么从一开始就使用 long 参数来确定,要么考虑稍后添加其他构造函数。或者,您可以引入一个可扩展的参数类。见下文。

问题 2: 构建器模式可用于多种场景。

  • 复杂对象创建

    当您处理具有许多属性的非常复杂的对象时 你最好只在对象创建时设置一次,用 常规构造函数会变得难以阅读,因为构造函数将 有一长串参数。将其发布为 API 不是好的风格 因为每个人都必须仔细阅读文档并确保 他们不会混淆参数。

    相反,当您提供构建器时,您只需要处理(私有(private)的) 构造函数接受所有参数,但是你的类的消费者可以 使用更具可读性的单独方法。

    Setter 不是一回事,因为它们允许您更改对象 创建后的属性。

  • 可扩展的 API

    当你只为你的类发布一个多参数构造函数时 决定你需要添加一个新的(可选的)属性(比如在你的软件的更高版本中) 您必须创建与第一个构造函数相同的第二个构造函数,但是 再接受一个参数。否则 - 如果您只是将它添加到现有的 构造函数 - 你会破坏与现有代码的兼容性。

    使用构建器,您只需为新属性添加一个新方法,所有现有 代码仍然兼容。

  • 不变性

    软件开发强烈倾向于并行执行 多个线程。在这种情况下,最好使用不能 在创建它们(不可变对象(immutable对象))之后进行修改,因为这些 不会导致来自多个线程的并发更新出现问题。这是 为什么 setter 不是一个选项。

    现在,如果你想避免多参数公共(public)构造函数的问题, 这使得构建器成为一个非常方便的替代方案。

  • 可读性(“Fluent API”)

    如果构建器的方法是 巧妙地命名,你可以写出读起来几乎像英语句子的代码。

一般来说,构建器是一种有用的模式,并且根据您使用的语言,对于 API 的提供者来说,它们要么非常易于使用(例如 Groovy),要么有点乏味(例如在 Java 中)。然而,对于消费者而言,它们可能同样简单。

关于面向对象的 JavaWorld : Getters/Setters vs Builder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6927292/

相关文章:

oop - 策略模式与开闭原则的冲突

entity-framework - Entity Framework 、MVVM 和计算类

java - 让一个线程启动另一个线程然后死掉

php - 在 PHP 中实现多级 "iterator"

PHP - 用不同数量的参数覆盖函数

C++:让包含类从包含类调用函数的问题

c++ - 实体组件架构 : want to split big entity -> hard to refactor

java - 我在获取 firebase 图像的 url 时遇到问题

java - 如何防止 Ant 在命令窗口中显示 [java]?

java - 比较具有多个数字但不是数组的变量 int