2013-04-02 5 views
3

У меня есть класс, который будет действовать как singleton.
Этот класс получит файл как часть конструктора. После этого класс готов к работе.
Так что в настоящее время я использую идиом с двойной проверкой-блокировкой и получаю экземпляр синглтона через static getInstance(), т. Е. Классический способ.
Моя проблема заключается в том, что в настоящее время я постоянно:Как я могу улучшить этот синглтон?

MySingleton.getInstance(theFile);

И theFile только нужно в первый раз одноточечно построен. После этого, т. Е. Как только синглтон был сконструирован, мне не нужно проходить в theFile.
Как мне это сделать?
Я думал создать MySingleton.getInstance();, но все равно это не сработало, так как вызывающий должен вызвать MySingleton.getInstance(theFile); первый раз, чтобы построить действительный класс.
Как я могу создать это лучше?

ответ

9

Объявление метода init(), который обрабатывает инициализацию с использованием файла.

Упростить getInstance(), чтобы вернуть экземпляр, но введите IllegalStateException, если init() еще не был вызван.

Например:

public class MySingleton { 

    private MySingleton INSTANCE; 

    // private constructor is best practice for a singleton 
    private MySingleton(File theFile) { 
     // initialize class using "theFile" 
    } 

    public static void init(File theFile) { 
     // if init previously called, throw IllegalStateException 
     if (INSTANCE != null) 
      throw new IllegalStateException(); 
     // initialize singleton 
     INSTANCE = new MySingleton(theFile); 
    } 

    public static MySingleton getInstance() { 
     // if init hasn't been called yet, throw IllegalStateException 
     if (INSTANCE == null) 
      throw new IllegalStateException(); 
     return INSTANCE; 
    } 

    // rest of class 
} 

Обратите внимание, что, хотя это не поточно, условия гонки было бы действительно мало, если таковые имеются, до тех пор, как init() называют еще часть вашего запуска сервера.

+1

@ sp00m Благодарим за редактирование. Я набрал это на моем iPhone:/ – Bohemian

+1

u r шучу меня .. вы набрали весь код на iphone !! оцените ваш энтузиазм, чтобы внести свой вклад. –

1

Может быть, вы можете предоставить способ инициализации синглета. Вы можете определить статический метод, называемый initialize(), который принимает файл и создает объект singleton - при запуске приложения или в соответствующем месте. После этого вы можете просто использовать getInstance().

0

Вы можете просто получить метод getInstance(), который не имеет параметра файла.

Он выдает исключение, если оно вызывается перед другим, но это нормально, поскольку в любом случае вы можете избежать передачи файла только в том случае, если вы уже уверены, что одноэлемент был создан ранее.

3

В типичной среде Injection Dependency ваше имя файла будет свойством для одноэлементного компонента, соответствующего этому одиночному классу, с областью действия как singleton. Затем вы просто вводите этот компонент в любой класс, который ему нужен.

Если ваша программа не имеет контейнера DI, то это имя файла должно быть либо свойством уровня приложения, полученным как аргумент JVM/через некоторый файл свойств или наихудший случай, константой в этом одноэлементном классе. Клиенты не должны беспокоиться о файле, который используется этим классом singleton.

0

Альтернатива + исключение init() метода,

Singleton::getInstance().load(myFile)

Просто убедитесь, это делается при запуске/независимо.

0

Альтернативный подход в первую очередь singletone with parameter is not a singletone.

Для решения этой проблемы у вас есть два варианта: сначала было описано в ссылке выше второй, чтобы получить ресурс изнутри.

Файл обычно связан с путем, вы можете получить доступ к этому пути из хранилища свойств, которое вы передаете/установите во время запуска приложения.

Возможная реализация такого механизма:

public enum MySingleton { 
INSTANCE; 

private final File theFiel; 

private MySingleton() { 
    this.theFile = initialize(MySystemProperties.getValue(MySystemProperties.MY_SINGLETONE_PATH); 

} 

private File initialize(String path) { 
    reutrn new File(path); // 

} 

} 
0

Единственный способ оптимизировать это не используя одноплодной шаблон на всех.

Серьезно. Ты стреляешь в ногу.

Когда вы начинаете передавать неиспользованные значения методам, должно быть действительно громких тревожных звонков, предупреждающих вас о том, что что-то архитектурно прогнило в государстве Дания. Очевидно, что вы можете игнорировать эти будильники (и, скорее всего, этот ответ тоже), но это не делает ваш код меньше. Я знаю, я здесь скучаю. Но все дело в том, что использование синглтонов превратит ваши программы в большие кучи парного спагеттизма.

There are | huge amounts | of posts | on why | singletons suck | more ass | than a | leech on | a donkey.

Поскольку я понятия не имею, что именно вы хотите достичь с этим классом, к сожалению, я не могу предложить решение.

Кроме этого: не используйте синглет.

Поздравляю вас позже. Он будет выглядеть тяжело, и он займет много места для чтения и экспериментов, но его правильное кодирование заставит вас чувствовать себя намного лучше. И превратит вас в лучшего программиста.

Смежные вопросы