开发者

Setting final variables via Factory Pattern

I am using GWT and am constrained to having zero argument constructors. This means that I am using a static factory method on each class in order to set member variables:

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...
}

Now the problem here is that x and y can 开发者_如何学编程not be final as I am setting them outside of the constructor, but ideally I want them to be immutable.

What is the best approach?


It's a good idea to have the language enforce as many properties of your program as possible, and making use of the final keyword is certainly good practice. But this is a case where the final keyword is just too strict to make the serialization mechanism of GWT work, at least in it's current state. Therefore you sadly can't make use of this feature.

But I think it's worth to mention that, if you don't provide setters for x and y and keep them private, you class indeed is immutable. It's just not the language enforcing this, it's your code.


The class only needs to have an empty constructor to support serialization. You can also have other constructors as well so you don't need your factory method. That said you can't have final variable because of the need for the zero argument constructors.

Hopefully this will be sorted out in a future release (See http://code.google.com/p/google-web-toolkit/issues/detail?id=1054)


Are you really constrained to a zero argument constructor? There might be a way telling GWT that you want to use a Constructor with Parameters. Anyway the suggestion of Waldheinz is the same thing i would have suggested.

But another thing to think about probably is, that GWT will use this default constrcutor to create an instance of this class at some point. So if your class depends on those two instance fields to have a valid value that could lead to errors.


If your zero-arg constructor constraint is only because of GWT-RPC, then you can overcome this using a custom field serializer: it has to be a class in the same package, named the same as the class to be serialized but with a _CustomFieldSerializer suffix and extending CustomFieldSerializer.
You can follow the java.lang.Boolean custom field serializer as an example. In your case, this should work:

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());
  }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜