Допустим, есть класс, описывающий точку на плоскости:
public final class Point {
private final double x;
private final double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
@Override
public String toString() {
return "Point(" + x + "; " + y + ")";
}
}
Статические поля
Выяснив, что чаще всего используется точка в координатах (0; 0), можно предложить пользователю использовать один и тот же объект везде, где нужна точка в начале координат.
public final class Point {
public static final Point ORIGIN = new Point(0, 0);
...
Статическое поле доступно извне: Point.ORIGIN. Объект, находящийся в этом поле, будет существовать в единственном экземпляре.
Теперь, когда клиенту этого класса нужна будет точка в начале координат, он сможет взять существующую (Point.ORIGIN), а не создавать новую.
Статические методы
Теперь вообще запретим создание новых экземпляров Point в начале координат.
public final class Point {
private static final Point ORIGIN = new Point(0, 0);
...
private Point(double x, double y) {
this.x = x;
this.y = y;
}
...
public static Point at(double x, double y) {
if (x == 0 && y == 0) {
return ORIGIN;
}
return new Point(x, y);
}
}
Мы добавили статический метод, который можно вызвать так: Point.at(x, y). Конструктор сделали приватным, чтобы новые экземпляры Point нельзя было создавать извне. Константу ORIGIN сделали приватной, т. к. это деталь реализации.
Теперь единственный способ получить точку — вызвать статический метод at. Point.at(0, 0) будет каждый раз возвращать один и тот же объект. at с любыми другими аргументами каждый раз будет возвращать новый объект.