Приватный конструктор в 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.