Приватный конструктор в Java — пример Singleton-паттерна

Если объявить конструктор класса с модификатором private, то снаружи этого класса создать его объект через new уже не получится. Этот приём часто используют для шаблона проектирования Singleton — когда нужно гарантировать существование только одного экземпляра класса.

Пример 1: программа для создания приватного конструктора

class Test {

  // create private constructor
  private Test () {
    System.out.println("This is a private constructor.");
  }

  // create a public static method
  public static void instanceMethod() {

    // create an instance of Test class
    Test obj = new Test();
  }

}

class Main {

  public static void main(String[] args) {

    // call the instanceMethod()
    Test.instanceMethod();
  }
}

Вывод:

This is a private constructor.

В примере выше мы создали приватный конструктор класса Test. Поэтому объект класса Test нельзя создать вне этого класса.

Именно поэтому мы добавили публичный статический метод instanceMethod() внутри класса, который и создаёт объект Test. А из класса Main мы уже вызываем этот метод по имени класса.

Пример 2: реализация Singleton на Java через приватный конструктор

Шаблон Singleton в Java гарантирует, что у класса будет только один экземпляр. Чтобы этого добиться, как раз и используют приватный конструктор.

class Language {

  // create a public static variable of class type
  private static Language language;

  // private constructor
  private Language() {
    System.out.println("Inside Private Constructor");
  }

  // public static method
  public static Language getInstance() {

     // create object if it's not already created
     if(language == null) {
        language = new Language();
     }

      // returns the singleton object
      return language;
  }

  public void display() {
      System.out.println("Singleton Pattern is achieved");
  }
}

class Main {
  public static void main(String[] args) {
     Language db1;

     // call the getInstance method
     db1= Language.getInstance();

     db1.display();
  }
}

Вывод:

Inside Private Constructor
Singleton Pattern is achieved

В примере выше мы создали класс Language, который содержит:

  • language — приватная переменная типа класса (private).

  • Language() — приватный конструктор (private).

  • getInstance() — публичный статический метод (public static), возвращающий объект класса.

  • display() — публичный метод (public).

Так как конструктор private, создавать объекты Language извне нельзя. Поэтому мы создаём объект внутри метода getInstance().

При этом условие написано так, что объект создаётся ровно один раз — и метод возвращает этот единственный объект.

Обратите внимание на строку:

db1 = Language.getInstance();

Здесь:

  • db1 — переменная типа Language.

  • Language.getInstance() — вызов метода getInstance().

Поскольку getInstance() возвращает объект класса Language, переменной db1 присваивается этот возвращённый объект.

В самом конце мы вызываем метод display() через этот объект.

Предупреждение

Этот вариант Singleton не потокобезопасен: если два потока одновременно зайдут в getInstance() при language == null, могут создаться два разных объекта. Для многопоточных приложений используйте synchronized или double-checked locking.