Вы можете ввести абстракцию как это:
public abstract class Singleton<T> {
private T object;
public synchronized T get() {
if (object == null) {
object = create();
}
return object;
}
protected abstract T create();
}
Тогда для каждого синглтона вам просто нужно написать это:
public final Singleton<Database> database = new Singleton<Database>() {
@Override
protected Database create() {
// connect to the database, return the Database instance
}
};
public final Singleton<LogCluster> logs = new Singleton<LogCluster>() {
...
Тогда вы можете использовать синглтоны, написав database.get()
. Если синглтон не был создан, он создается и инициализируется.
Причина, по которой люди, вероятно, не делают это и предпочитают просто несколько раз написать что-то вроде этого:
private Database database;
public synchronized Database getDatabase() {
if (database == null) {
// connect to the database, assign the database field
}
return database;
}
private LogCluster logs;
public synchronized LogCluster getLogs() {
...
Это связано с тем, что в конце для каждого синглтона остается только еще одна строка кода, и вероятность ошибочного использования шаблона инициализации-синглтона довольно мала.