0

在我过去的开发过程中,我一直在考虑这个问题。

我有点反对做这样的事情,我通常声明一个单独的方法来明确处理逻辑。

例如

如果一个类有一个返回对象列表的方法,我认为直接通过它的 getter 方法修改这个集合是个坏主意。

 Public Class ReportGenerator{

    private List<Configurations> configurations;

    List<Configuration> getConfigurations (){
      return this.configurations;
    }

    }

我认为通过执行以下操作是不好的做法:

getConfigurations().remove(1); //remove a configuration via a getter

我会使用以下方法:

 Public Class ReportGenerator{

            private List<Configurations> configurations;

          public  List<Configuration> getConfigurations (){
              return Collections.unmodifiableList(this.configurations);
            }


          public void removeConfiguration(int index) //logic explicitly handle the remove
              { 
              this.configurations.remove(index);
            }

          }

然而,我想到的还有一件事是,如果 Configuration 对象也有 getter 和 setter,那么你不能通过这样做来阻止其他人

  reportGenerator.getConfigurations().get(0).settTitle("test");

他们仍然可以通过使用 ReportGenerator 的 getter 方法来更改 Configuration 对象的状态,我认为这是不允许的。但是如果我们想防止这种情况发生,我们必须在 ReportGenerator 类中声明更多方法来将调用转发到 Configuration 对象,并使用防御性副本。

所以我的问题是,如果您有一个对象 A,其中包含另一个使用组合的对象 B,并且它们都有 getter 和 setter,您是否更喜欢通过 A 的 getter 方法更改对象 B 的状态?例如

A.getB().setTitle("");

还是您更喜欢向 A 添加方法以更改 B 的状态(基本上将调用转发到 B)

例如

A.setBTitle("");

在此方法内部,A 调用 B.setTitle("");

很抱歉这个问题很长,我想我不确定我到底想问什么。希望你能理解。:P

4

3 回答 3

1

这可能适用于较小的类,但我会为您必须如何维护更复杂的对象层次结构而感到不寒而栗。想象一下,如果A突然有几个对象作为字段。你认为在它们每个周围加上一个包装器是个好主意吗?然后考虑在每个对象变得更加复杂时这样做。有时做A.getB().getC().setThingamabob()比写A.setSomething()which calls B.setCField()which calls更容易C.setThingamabob()

如果您认为对象不应该是可变的,请删除设置器。如果消费者A根本不需要更改B,请不要提供getB()方法,而是提供类似于 的A.setThingy()内容,其中没有提到设置的内容是 的一部分B

您的 API 契约并不一定意味着您的类必须为其所有属性提供 getter/setter。如果属性不打算由消费者直接读取/修改,请不要提供这样做的方法。

于 2013-05-19T04:46:29.110 回答
0

当您编写代码时,最重要的是清晰性。您可以做您需要的事情,甚至更改实例状态,但是如果可以的话,我会避免这样做。除非您有一个很好的案例,即使用延迟初始化(在您第一次访问它时创建一个对象或值)。

最后它真的取决于但我会尽量不改变getter上的对象状态。

貌似其他人也这么想

.. 何时可以更改属性获取器访问的对象状态(例如初始化)?

于 2013-05-19T04:30:52.070 回答
0

是否是不好的做法的答案是:“这取决于”。

一方面,返回对其内部状态的引用的类是“泄漏抽象”。由于许多理论上的原因,这是不好的:

  • 在 API 中显示类实现细节会鼓励对这些细节的依赖,这使得更改它们变得更加困难。(这在这里绝对不是问题,但是如果您设计 API 以便修改 getter 返回的内容是更改事物的标准方法,那么这可能很难处理......)

  • 如果细节显示为不可变的数据结构,客户端仍然可以看到“实时”更改,如果应用程序是多线程的,这可能是一个问题。

  • 如果细节显示为可变数据结构,则客户端可以直接更改类的状态,绕过类通常执行的任何假设检查等。

  • 如果该类在某些情况下是“安全敏感的”,那么如果抽象是泄漏的,那么您将获得各种额外的“向量”来破坏安全性。

另一方面,使抽象不泄漏可能会很昂贵:

  • 必须分配不可修改的集合包装器,并且它们增加了额外级别的方法调用。

  • 返回副本会导致复制数据的额外开销。在多线程环境中,您可能需要在制作副本时锁定源数据结构。

最后,如果 API 需要允许客户端进行更改,那么通过泄漏抽象进行更改实际上可能会为您提供更简单的 API 设计。可以通过(例如)使相关方法“包私有”来缓解泄漏问题。

所以总结起来就是“好的OO设计”和务实的问题之间的取舍。您需要根据具体情况权衡这些。


顺便说一句,您的问题标题和描述具有误导性。例如

  getConfigurations().remove(1); //remove a configuration via a getter

这是误导。您不是“通过吸气剂”删除配置。您正在通过 getter 返回的对象删除它!

(我在吹毛求疵,但如果你想让人们理解你,你需要使用他们理解的语言。)

于 2013-05-19T05:38:23.487 回答