Ограничение класса одним экземпляром без использования синглтона?

1

Я не хочу использовать singleton, но я просто не могу разрешить более одного экземпляра моего класса.

Считаете ли вы это хорошим подходом, а если нет, то какой лучший способ?

public class SoundSystem {

    private static boolean instanceCreated = false;

    public SoundSystem() {
        if(instanceCreated) {
            throw new IllegalStateException("Only one instance can be created.");
        }

        instanceCreated = true;
    }
}
  • 6
    Вы не хотите использовать синглтон, но вы хотите синглтон. Как насчет того, чтобы сказать, почему вы не хотите использовать синглтон, и что вы подразумеваете под этим?
  • 0
    Ну, я читал во многих местах, что синглтон - это запах кода, и я должен согласиться, что это не очень красиво. Я только хочу ограничить количество экземпляров.
Показать ещё 5 комментариев
Теги:
singleton

4 ответа

4
Лучший ответ

Это синглтон, даже если вы не применяете его в "традиционной" манере. Я не рекомендую этот подход, и я думаю, вы должны найти другой путь.

Например, почему бы не создать один экземпляр SoundSystem при запуске вашей программы? Вам не нужно явно вводить в действие его единство, просто передайте этот экземпляр вместе с другими объектами, которым необходим доступ к звуковой системе. В качестве бонуса это также позволяет легко отказаться от поддержки различных типов SoundSystem если вам это понадобится в какой-то день (приятная небольшая дополнительная выгода, даже если вам это не нужно).

Кроме всего прочего, сама инициализация OpanAL сама потерпит неудачу, если вы попытаетесь инициализировать несколько SoundSystem? Если нет, то на самом деле нет причины устанавливать искусственный лимит. Если это так, то вы можете просто позволить OpanAL определить, что такое и не является ошибкой. Но в любом случае это не было бы риском, если бы просто просто создать один экземпляр и передать его, вместо того чтобы позволить всем вашим классам приложений запрашивать сам экземпляр.

Будьте осторожны, вы не попадаете в ловушку проблем XY. Синглтоны не являются по своей природе злыми, но по какой-то причине их часто злоупотребляют, следовательно, общий совет против них. Обычно есть более чистый способ, и эти более чистые способы обычно приносят много бонусов. Подумайте о реальной проблеме, которую вы пытаетесь решить/ситуации, которую вы пытаетесь избежать здесь.

  • 0
    Что вы думаете о выполнении инициализации в статическом блоке? Это кажется хорошим способом, если только у него нет недостатков, о которых я не знаю.
  • 0
    @MightyPork То же мнение! В многопоточной среде статический блок - это многопоточный подход, если необходимо использовать синглтон. В однопоточной среде это, по сути, просто синоним того, что вы уже делаете. Рефакторинг вашего кода для обеспечения той же функциональности в статическом блоке просто выражает тот же концептуальный дизайн по-другому. Так что мое мнение такое же; синглтоны - это синглтоны, независимо от того, как вы их применяете. Вы спросили о «хорошем подходе», поэтому вы, похоже, заинтересовались концептуальными подходами к проектированию; статический блок в основном такой же, как и сейчас.
Показать ещё 1 комментарий
2

Нет, это не очень хороший подход.

Давайте возьмем быстрый пример в контексте многопоточности.

Thread 1 создает экземпляр SoundSystem, if(instanceCreated) возвращает false, прежде чем менять instanceCreated на true, прерыватель планировщика Thread 1. Теперь Thread 2 также может создавать SoundSystem поскольку isInstanceCreated в это время является ложным.

Но в конце оба потока будут иметь другой экземпляр.

  • 0
    Возможно, он пишет однопоточную программу.
  • 0
    Да, это действительно так, но я думаю, что в конце концов я буду придерживаться статического блока, что позволит избежать этих проблем в целом.
0

Вы можете использовать перечисление, если вы готовы сделать все свои поля 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

  • 0
    Я пытаюсь избежать запаха кода здесь, не стремясь представить другой, еще хуже.
0

Решение, которое вы разместили, позволяет использовать садовое разнообразие "состояние гонки". Два объекта, пытающихся создать вашу SoundSystem одновременно, могут привести к созданию экземпляра.

Возможно, все методы и переменные статического звука SoundSystem получат то, что вы хотите, но это трудно узнать без дополнительной информации.

  • 0
    Было бы неплохо прокомментировать, почему этот ответ был отклонен. Я здесь, чтобы учиться.
  • 0
    О том, чтобы все это было статичным, не может быть и речи, потому что мне нужно, чтобы он реализовал определенные интерфейсы ... но вы понимаете, с каким состоянием гонки.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню