Используете статические в Java синглтоны? - PullRequest
0 голосов
/ 24 сентября 2010

Я создаю одноэлементный сервис на Java для Android:

final class MyService {

    private static Context context = null;
    // ...

    private MyService() {
        myObj = new MyObj(context);
            // ...  
    }                       
    private static class Singleton {
        private static final MyService INSTANCE = new MyService();
    }

    /**
     *  a singleton - do not use new(), use getInstance().
     */
    static synchronized myService getInstance(Context c) {
        if (context == null) context = c;
        return Singleton.INSTANCE;
    }

Для повышения производительности я использую статические переменные и методы.

Мои вопросы:

  • для объектов new () обеспечивает возможность инициализировать этот объект перед его использованием. Есть эквивалент для статического класса? За пример: когда статические методы зависят при более ранних инициализациях - такие что касается «контекста» выше - есть ли средство обеспечения того, чтобы инициализация происходит первой? Должен я бросить исключение, если их нет?

  • так как все это статично, я ожидаю, что есть только сам класс: есть что синглтон по определению? Является рекомендуемый код выше только способ предотвращения реализации объекты?

Заранее спасибо!

Ответы [ 4 ]

2 голосов
/ 24 сентября 2010

Это, безусловно, один из способов создания синглтона.Я думаю, что вы могли бы покончить со статическим помощником;статичность по соображениям производительности на самом деле не сильно экономит, и это запутывает код.

Я думаю, что ваш реальный вопрос в том, можно ли отложить создание статики до тех пор, пока context не станет нулевым.Ответ зависит от ВМ;в большинстве «ванильных» Java-виртуальных машин INSTANCE фактически не будет создаваться до первого вызова GetInstance();статика лениво оценивается для лучшей производительности при запуске.Это означает, что если у context есть что-то еще до первого звонка на GetInstance(), у вас все хорошо.

Однако, простите меня, но я не знаю, отличается ли это поведение на виртуальной машине Android, которая технически не является «настоящей» виртуальной машиной Java (или так говорит Sun / Oracle).Чтобы быть в безопасности, если context не имеет экземпляра к моменту вызова статического конструктора, я бы хотел рассмотреть его в статическом конструкторе с помощью статического метода фабрики или простого IoC, прежде чем создавать экземпляр INSTANCE.

1 голос
/ 25 сентября 2010

Вы можете добавить статический блок инициализации в свой класс

public class MySingleton {
    /* Default constructor */
    private MySingleton() {
    }

    static {
          //Static init stuff...
        }
        ...
    }
}

Статический блок инициализатора будет вызываться один раз для каждого загрузчика классов, в который загружается класс, - как правило, только один раз за время существования процесса.

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

0 голосов
/ 08 ноября 2018

Избегайте чрезмерной инженерии.Вместо этого используйте enum.

Хотя этот подход еще не получил широкого распространения, одноэлементный тип перечисления является лучшим способом реализации синглтона.

Джошуа Блох

Подход объяснен в этом посте Джошуа Блохом.

0 голосов
/ 25 сентября 2010

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

Если намерение состоит в том, чтобы возвращать одинаковый экземпляр для каждого специфический контекст, я бы использовал что-то вроде этого:

public class Service {
    private static final Map<Context, Service> services = new HashMap<Context, Service>();
    private Context context;

    private Service(Context context) {
        this.context = context;
    }

    public static synchronized Service getInstance(Context context) {
        Service service = services.get(context);
        if (service == null) {
            service = new Service(context);
            services.put(context, service);
        }
        return service;
    }
}

Это называется Multiton .Это своего рода комбинация Factory и Flyweight .модификатор synchronized довольно дорогой при широком использовании, вы можете использовать ReentrantReadWriteLock.Статья в Википедии содержит пример.

Возвращаясь к истории синглтона, Википедия имеет несколько хороших примеров .Базовый, который создает синглтон во время загрузки класса, и другой, который создает синглтон по первому запросу.Но, как правило, использование этого шаблона не рекомендуется.

...