通过工厂模式设置最终变量

时间:2011-07-15 13:44:05

标签: java gwt immutability factory-pattern

我正在使用GWT并且被限制为具有零参数构造函数。 这意味着我在每个类上使用静态工厂方法来设置成员变量:

public class Point {
    private final float x;
    private final float y;

    public static Point build(float x, float y) {
        Point p = new Point();
        p.x = x;
        p.y = y;
        return p;
    }

    // getters for x and y
    // other methods...
}

现在问题是x和y不能是final,因为我将它们设置在构造函数之外,但理想情况下我希望它们是不可变的。

最好的方法是什么?

4 个答案:

答案 0 :(得分:3)

让语言尽可能多地执行程序属性是一个好主意,并且使用final关键字肯定是一种很好的做法。但是这种情况下final关键字过于严格,无法使GWT的序列化机制起作用,至少在当前状态下是这样。因此,你遗憾地无法使用这个功能。

但我认为值得一提的是,如果你不为x和y提供setter并保留它们private,那么你的类确实是不可变的。这不是强制执行此操作的语言,而是您的代码。

答案 1 :(得分:2)

该类只需要一个空构造函数来支持序列化。您也可以使用其他构造函数,因此您不需要工厂方法。这就是说你不能拥有最终变量,因为需要零参数构造函数。

希望这将在以后的版本中进行整理(参见http://code.google.com/p/google-web-toolkit/issues/detail?id=1054

答案 2 :(得分:0)

你真的被限制为零参数构造函数吗?可能有一种方法告诉GWT您想要使用带有参数的构造函数。无论如何,Waldheinz的建议与我建议的一样。

但另一件需要考虑的事情是,GWT将使用这个默认的constrcutor在某个时刻创建这个类的实例。因此,如果您的类依赖于这两个实例字段来获得可能导致错误的有效值。

答案 3 :(得分:0)

如果您的零arg构造函数约束仅仅是因为GWT-RPC,那么您可以使用自定义字段序列化器来克服这个问题:它必须是同一个包中的一个类,命名相同作为要序列化的类但具有_CustomFieldSerializer后缀并扩展CustomFieldSerializer 您可以关注the java.lang.Boolean custom field serializer作为示例。在你的情况下,这应该工作:

public final class Point_CustomFieldSerializer extends CustomFieldSerializer<Point> {
  @Override
  public boolean hasCustomInstantiateInstance() { return true; }

  @Override
  public Point instantiateInstance(SerializationStreamReader streamReader) throws SerializationException {
     return new Point(streamReader.readInt(), streamReader.readInt());
  }

  @Override
  public void deserializeInstance(SerializationStreamReader streamReader, Point instance) throws SerializationException {
    // everything is done in instantiateInstance
  }

  @Override
  public void serializeInstance(SerializationStreamWriter streamWriter, Point instance) throws SerializationException {
    streamWriter.writeInt(instance.getX());
    streamWriter.writeInt(instance.getY());
  }
}