5

我参与了这个项目,我们正在构建大量遗留代码。我有一个关于必须通过网络传输的大型 java bean 对象的特殊情况。所以我的第一个想法是让它不可变和可序列化来做这个把戏。在这一点上,我面临着一些困难的选择:-

  1. 理想情况下,我想要某种方法来自动生成此类的不可变、可序列化版本。我没有以任何方式重构或更改此类的范围,我真的很讨厌必须复制粘贴具有不同名称的类?

  2. 假设我放弃了 1 即我实际上选择了复制 HUGE javabean 类的代码,我仍然会处于不得不编写一个带有 20-25 个参数的构造函数以使这个类不可变的糟糕情况。除了构造函数注入之外,使类不可变的更好方法是什么?

谢谢并恭祝安康,

4

6 回答 6

4

要使其真正不可变,您需要在构造时初始化成员。

一种方法(我不是说它很漂亮!)这样做并避免构造函数中的巨大参数列表是拥有一个具有相同属性的可变类型。通过“setters”一次设置一个可变类型的属性,然后将可变对象作为单个参数传递给不可变类型的构造函数。然后,不可变对象将属性从可变源复制到它自己的 ( final) 成员。

您也可以考虑“有效的不变性”。也就是说,即使系统没有强制执行不变性,您也可以使用将初始化阶段与使用阶段明确分开的编码实践。毕竟,序列化不需要不变性。

您可以更进一步,为不公开实现属性的接口创建实现隐藏包装器。包装器仅通过委托给“真实”实现来实现接口中的方法。实现中的 setter 和 getter 不存在于包装器中。这将阻止客户端简单地从接口向下转换到实现类并操作属性。

于 2009-04-15T20:01:24.397 回答
4

Joshua Bloch 的“Effective Java”说明了 Builder 模式,其中简单的 Builder 对象用于构造具有长构造函数参数列表的复杂对象。我会推荐它。

http://www.drdobbs.com/java/208403883;jsessionid=PJWS41F5DJ4QRQE1GHRSKH4ATMY32JVN?pgno=2

于 2010-03-24T21:51:16.433 回答
1

包含 getter 的简单只读接口怎么样?

如果 bean 类是你自己的,让它简单地实现接口并在创建后只使用接口。

如果您无法控制 bean 类,您还可以创建一个 getter 接口并通过为该 getter 接口创建一个代理来实现它,该代理使用调用处理程序将所有方法调用委托给 bean。

于 2010-03-24T21:59:53.233 回答
1

20-25 个属性对于一次性来说并不大,特别是如果您使用的是一个半体面的编辑器。

如果在构造不可变版本时已经有一个可变实例,只需将其传递给构造函数即可。

如果你想成为真正邪恶的 hacky,请使用为可变类或子类实现java.beans创建可序列化。或者,您可以使用XML 序列化(可以通过 Java 序列化发送的 XML ......)。MapExternalizablejava.beans

于 2009-04-15T20:14:44.693 回答
0

第 1 步:创建一个新类并为其提供与“大 Java bean 对象”的实例变量名称完全相同的实例变量。那个新类不应该有设置器(但只有获取器)以使其不可变。

第 2 步:使用 Apache Commons BeanUtils.copyProperties将所有属性(即实例变量)从“大 java bean 对象”复制到新对象。

于 2009-04-15T23:50:12.367 回答
0

一些想法:

受保护的 setter 和工厂方法 您可以使用受保护的 setter 方法定义 bean,并在同一个包中定义一个工厂类,该工厂类接受所有参数并调用这些 setter。bean 在该包之外是不可变的。要强制执行此操作,请务必密封您的 jar,以便最终用户无法在同一个包中创建新类。

注意:您可以使用我的 JavaDude Bean 注释来简化创建: http ://code.google.com/p/javadude/wiki/Annotations

例如:

@Bean(writer=Access.PROTECTED, // all setXXX methods will be protected
    properties={
        @Property(name="name"),
        @Property(name="age", type=int.class)
    })
public class Person extends PersonGen {
}

在eclipse中创建getter和构造函数

Eclipse 有一些很好的工具可以使这个速度更快:

  1. 创建 bean 类
  2. 添加你想要的字段
  3. 在编辑器窗口中单击鼠标右键
  4. 选择 Source->Generate Getter and Setter
  5. 按“选择吸气剂”按钮
  6. 按确定
  7. 在编辑器窗口中单击鼠标右键
  8. 选择 Source->Generate Constructors from fields
  9. 在构造函数中选择并排序您想要的字段
  10. 按确定

不变性装饰器

另一个想法是用 getter 和 setter 定义你的 bean(你可以使用上述技术,但包括 setter),然后你可以为它创建一个只有 getter 的包装类。

于 2009-04-16T16:14:46.007 回答