Моя проблема касается дизайна API.
Допустим, я проектирую вектор (математический / физический смысл).Я хотел бы иметь как неизменяемую, так и изменяемую реализацию.
Тогда у меня есть вектор, который выглядит следующим образом:
public interface Vector {
public float getX(); public float getY();
public X add(Vector v);
public X subtract(Vector v);
public X multiply(Vector v);
public float length();
}
Интересно, как я могу гарантировать, что оба изменяемыеи неизменная реализация.Мне не очень нравится подход java.util.List (допускающий изменчивость по умолчанию) и UnsupportedOperationException (), который имеет неизменяемая реализация Guava.
Как я могу разработать «идеальный» интерфейс или абстрактный класс Vector с обоимиэти реализации?
Я думал о чем-то вроде этого:
public interface Vector {
...
public Vector add(Vector v);
...
}
public final class ImmutableVector implements Vector {
...
public ImmutableVector add(Vector v) {
return new ImmutableVector(this.x+v.getX(), this.y+v.getY());
}
...
}
public class MutableVector implements Vector {
...
public MutableVector add(Vector v) {
this.x += v.getX();
this.y += v.getY();
return this;
}
...
}
В общем, я хотел бы проверить, есть ли у этого подхода вопиющие недостатки дизайна, что они и чтоя должен сделать это, чтобы исправить это?
Примечания: "вектор" - пример более общего случая использования.Ради моего вопроса я мог бы переписать интерфейс List или что-то еще.Пожалуйста, обратите внимание на более общий случай использования.
Окончательный выбор после ответов ниже, основанный на времени Joda, как кто-то объяснил, но теперь отредактировал:
/** Basic class, allowing read-only access. */
public abstract class ReadableVector {
public abstract float getX(); public abstract float getY();
public final float length() {
return Vectors.length(this);
}
// equals(Object), toString(), hashCode(), toImmutableVectors(), mutableCopy()
}
/** ImmutableVector, not modifiable implementation */
public final class ImmutableVector extends ReadableVector implements Serializable {
// getters
// guava-like builder methods (copyOf, of, etc.)
}
/** Mutable implementation */
public class Vector extends ReadableVector implements Serializable {
// fields, getters and setters
public void add (ReadableVector v) {/* delegate to Vectors */}
public void subtract(ReadableVector v) {/* delegate to Vectors */}
public void multiply(ReadableVector v) {/* delegate to Vectors */}
}
/** Tool class containing all the logic */
public final class Vectors {
public static ImmutableVector add(ReadableVector v1, ReadableVector v2) {...}
public static void addTo(Vector v1, ReadableVector v2) {...}
...
}
Я изменил Вектор синтерфейс к абстрактному классу, потому что в основном вектор не должен быть ничем иным.
Спасибо всем.