Синглтон и исключение - PullRequest
29 голосов
/ 18 февраля 2010

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

Здесь у меня есть Singleton (используя метод Билла Пью, описанный в Wiki для Singleton).

    private static class SingletonObjectFactoryHolder{
    //1  
        private static final ObjectFactory INSTANCE = new ObjectFactory();
    }

    private ObjectFactory() throws Exception{
    //2
            //create the factory
    }


    public static ObjectFactory getInstance(){
    //3
        return SingletonObjectFactoryHolder.INSTANCE;
    }

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

Итак, мой единственный вариант вернуть нулевой объект, если одноэлементный объект не был создан правильно?

Спасибо

P.S Я понимаю, что этот синглтон может сломаться, если он загружен через разные загрузчики классов или если загружен рефлексивно, но он достаточно хорош для моей цели.

// UPDATE

Мне любопытно, не могу ли я изменить свой дизайн, как показано ниже, для исключения?

Кроме того, мне не нужна синхронизация (загрузчик классов гарантирует, что статический внутренний класс будет загружен только один раз и только при вызове getInstance ()). Таким образом, потокобезопасный и ленивый экземпляр?

 private static class SingletonObjectFactoryHolder{
        //1  
           public static ObjectFactory getInstance() throws Exception{
         return new ObjectFactory();
           }
 }

 private ObjectFactory() throws Exception{
        //2
        //create the factory
 }


 public static ObjectFactory getInstance(){
        //3
    return SingletonObjectFactoryHolder.getInstance();
 }

Еще раз спасибо.

Ответы [ 4 ]

35 голосов
/ 18 февраля 2010

Используйте статический инициализатор и сбросьте Exception как ExceptionInInitializerError. Нажмите на ссылку, чтобы прочитать Javadoc, и вы увидите, что он подходит именно для этого конкретного функционального требования: обработка исключений во время статической инициализации . Фактически, синглтон является не чем иным, как статически и лениво инициализированным глобальным объектом.

private static class SingletonObjectFactoryHolder{
    private static final ObjectFactory INSTANCE;
    static {
        try {
            INSTANCE = new ObjectFactory();
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
}

Нет необходимости в двойной проверке блокировки идиома, которая считается анти-паттерном, а в некоторых случаях даже небезопасной.

0 голосов
/ 18 февраля 2010

Вы можете проверить наличие нулевого INSTANCE внутри getInstance и лениво его инициализировать. Но обычно лучше, если конструкторы не генерируют, если вы можете сделать конструктор более безопасным, что, вероятно, будет лучше.

0 голосов
/ 18 февраля 2010

Я согласен с Арне Бурмейстером, код для которого будет выглядеть так:

private static class SingletonObjectFactoryHolder
{
    private static ObjectFactory INSTANCE;


    private ObjectFactory() 
    {

    }

    public static String getInstance() throws Exception
    {
      return (INSTANCE == null) ? (INSTANCE = new ObjectFactory()) : INSTANCE; 
     // A ternary operator might not be the best fit if you need to throw an exception, but I think it looks nicer than the if(INSTANCE==null){} else{} for lazy instantiation.
    }

}
0 голосов
/ 18 февраля 2010

Только не выбрасывайте исключение из конструктора объекта. Вы можете предоставить init () метод и выбросить оттуда исключение, если это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...