Я бы согласился с другими авторами и сказал бы, что это кажется излишним, но сказал, что я думаю, что это то, что младший разработчик может ошибиться.Я думаю, что, поскольку поведение поставщика, который создает синглтон (показанный ниже), будет одинаковым почти во всех случаях, я бы хотел поставить это как поведение по умолчанию в LazyThreadSafeInstantiator
.Использование аннонимного внутреннего класса каждый раз, когда вы хотите использовать синглтон, действительно грязно.
@Override
public Singleton1 get() {
return new Singleton1();
}
Это можно сделать, предоставив перегруженный конструктор, который переводит класс в необходимый синглтон.
public class LazyThreadSafeInstantiator<T> implements Supplier<T> {
private final Supplier<T> instanceSupplier;
private Class<T> toConstruct;
private volatile T obj;
public LazyThreadSafeInstantiator(Supplier<T> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
public LazyThreadSafeInstantiator(Class<t> toConstruct) {
this.toConstruct = toConstruct;
}
@Override
// http://en.wikipedia.org/wiki/Double-checked_locking
public T get() {
T result = obj; // Wikipedia: Note the usage of the local variable result which seems unnecessary. For some versions of the Java VM, it will make the code 25% faster and for others, it won't hurt.
if (result == null) {
synchronized(this) {
result = obj;
if (result == null) {
if (instanceSupplier == null) {
try {
Constructor[] c = toConstruct.getDeclaredConstructors();
c[0].setAccessible(true);
result = c[0].newInstance(new Object[] {});
} catch (Exception e) {
//handle
}
result =
} else {
result = instanceSupplier.get();
}
obj = result;
}
}
}
return result;
}
}
Это будет использоваться следующим образом.
private static final Supplier<Singleton1> instanceHolder =
new LazyThreadSafeInstantiator<Singleton1>(Singleton1.getClass());
Это мое мнение немного чище.Вы можете расширить это, чтобы использовать аргументы конструктора.