Я не хочу использовать singleton, но я просто не могу разрешить более одного экземпляра моего класса.
Считаете ли вы это хорошим подходом, а если нет, то какой лучший способ?
public class SoundSystem {
private static boolean instanceCreated = false;
public SoundSystem() {
if(instanceCreated) {
throw new IllegalStateException("Only one instance can be created.");
}
instanceCreated = true;
}
}
Это синглтон, даже если вы не применяете его в "традиционной" манере. Я не рекомендую этот подход, и я думаю, вы должны найти другой путь.
Например, почему бы не создать один экземпляр SoundSystem
при запуске вашей программы? Вам не нужно явно вводить в действие его единство, просто передайте этот экземпляр вместе с другими объектами, которым необходим доступ к звуковой системе. В качестве бонуса это также позволяет легко отказаться от поддержки различных типов SoundSystem
если вам это понадобится в какой-то день (приятная небольшая дополнительная выгода, даже если вам это не нужно).
Кроме всего прочего, сама инициализация OpanAL сама потерпит неудачу, если вы попытаетесь инициализировать несколько SoundSystem
? Если нет, то на самом деле нет причины устанавливать искусственный лимит. Если это так, то вы можете просто позволить OpanAL определить, что такое и не является ошибкой. Но в любом случае это не было бы риском, если бы просто просто создать один экземпляр и передать его, вместо того чтобы позволить всем вашим классам приложений запрашивать сам экземпляр.
Будьте осторожны, вы не попадаете в ловушку проблем XY. Синглтоны не являются по своей природе злыми, но по какой-то причине их часто злоупотребляют, следовательно, общий совет против них. Обычно есть более чистый способ, и эти более чистые способы обычно приносят много бонусов. Подумайте о реальной проблеме, которую вы пытаетесь решить/ситуации, которую вы пытаетесь избежать здесь.
Нет, это не очень хороший подход.
Давайте возьмем быстрый пример в контексте многопоточности.
Thread 1 создает экземпляр SoundSystem
, if(instanceCreated)
возвращает false, прежде чем менять instanceCreated
на true, прерыватель планировщика Thread 1. Теперь Thread 2 также может создавать SoundSystem
поскольку isInstanceCreated
в это время является ложным.
Но в конце оба потока будут иметь другой экземпляр.
Вы можете использовать перечисление, если вы готовы сделать все свои поля final
. У этого тоже есть некоторый "запах кода". Он будет защищать от многопоточных проблем, но имеет ограничение на то, что все ваши переменные экземпляра SoundSystem
должны быть окончательными.
public enum SoundSystem {
INSTANCE("Hello", "World");
private final Object field1;
private final Object field2;
private SoundSystem(Object field1, Object field2) {
this.field1 = field1;
this.field2 = field2;
}
@Override
public String toString() {
return field1.toString() + " " + field2.toString();
}
public Object getField1() {
return this.field1;
}
public Object getField2() {
return this.field2;
}
//etc., etc.
}
Затем вы можете использовать SoundSystem.INSTANCE
чтобы получить доступ к вашему элементу singleton
Решение, которое вы разместили, позволяет использовать садовое разнообразие "состояние гонки". Два объекта, пытающихся создать вашу SoundSystem одновременно, могут привести к созданию экземпляра.
Возможно, все методы и переменные статического звука SoundSystem получат то, что вы хотите, но это трудно узнать без дополнительной информации.