Установка конечных переменных с помощью Factory Pattern - PullRequest
2 голосов
/ 15 июля 2011

Я использую 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 не могут быть окончательными, поскольку я устанавливаю их вне конструктора, но в идеале я хочу, чтобы они были неизменяемыми.

Каков наилучший подход?

Ответы [ 4 ]

3 голосов
/ 15 июля 2011

Хорошей идеей будет заставить язык применять как можно больше свойств вашей программы, и использование ключевого слова final, безусловно, является хорошей практикой. Но это тот случай, когда ключевое слово final слишком строго, чтобы заставить механизм сериализации GWT работать, по крайней мере, в его текущем состоянии. Поэтому вы, к сожалению, не можете использовать эту функцию.

Но я думаю, что стоит упомянуть, что, если вы не предоставляете установщики для x и y и сохраняете их private, вы действительно класс неизменен . Это не язык, обеспечивающий это, это ваш код.

2 голосов
/ 15 июля 2011

Класс должен иметь только пустой конструктор для поддержки сериализации. Вы также можете иметь другие конструкторы, так что вам не нужен ваш фабричный метод. Тем не менее, вы не можете иметь окончательную переменную из-за необходимости в конструкторах с нулевым аргументом.

Надеюсь, это будет решено в будущем выпуске (см. http://code.google.com/p/google-web-toolkit/issues/detail?id=1054)

0 голосов
/ 16 июля 2011

Если ваше ограничение конструктора с нулевым аргументом связано только с GWT-RPC, то вы можете преодолеть это с помощью настраиваемого полевого сериализатора: это должен быть класс в том же пакете, названный так же, как сериализуемый класс, но с суффиксом _CustomFieldSerializer и расширением CustomFieldSerializer.
В качестве примера можно использовать сериализатор настраиваемых полей java.lang.Boolean . В вашем случае это должно работать:

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 голосов
/ 15 июля 2011

Вы действительно ограничены конструктором с нулевым аргументом? Может быть способ сообщить GWT, что вы хотите использовать конструктор с параметрами. В любом случае, предложение Вальдхайнца - это то же самое, что я бы предложил.

Но еще одна вещь, о которой стоит подумать, это то, что GWT будет использовать этот конструктор по умолчанию для создания экземпляра этого класса в некоторый момент. Поэтому, если ваш класс зависит от этих двух полей экземпляра, чтобы иметь допустимое значение, которое может привести к ошибкам.

...