#java #android
#java #Android
Вопрос:
Иногда я вижу, что люди создают самостоятельный экземпляр, например:
public class Example extends Service
{
private static Example mInstance = null;
public void onStart( Intent aIntent, int aStartId )
{
mInstance = this;
.
.
.
}
}
Какова цель этого?
Комментарии:
1. Невозможно сказать с небольшим количеством кода, который вы опубликовали. Это может быть одноэлементный класс.
Ответ №1:
Это называется одноэлементным шаблоном проектирования. Синглтоны используются, когда будет один экземпляр объекта, выполняющий операции с нестатическими данными.
Смотрите здесь .
Комментарии:
1. Это не одноэлементный шаблон. Он также не ограничивает создание объекта с помощью непубличного конструктора и не создает его, когда это необходимо в первый раз.
2. Ну, это может быть. OP вырезал много кода. Если это не синглтон, то это класс с серьезными проблемами.
3. Этот точный код не является полноценным одноэлементным дизайном, нет. Однако, учитывая, что переменная экземпляра является частной и статической, синглтон будет иметь наибольший смысл для данного кода. Если программа просто хочет использовать экземпляр в коде, она может использовать ключевое слово this .
4. На самом деле, это почти наверняка не является частью одноэлементного шаблона, поскольку
mInstance
не задается в конструкторе. Кроме того,Service
объект Android не может быть реализован как одноэлементный; фреймворк должен иметь доступ к конструктору по умолчанию дляService
класса.5. Верно, я согласен, но OP задавал общий вопрос о частных статических переменных экземпляра. В общем, частные статические переменные экземпляра являются либо одноэлементным шаблоном, либо плохой практикой. В конкретном случае опубликованного кода это, вероятно, просто плохая практика, поскольку на экземпляр можно ссылаться с помощью Example.this
Ответ №2:
В дополнение к тому, что другие ответы указывают на одноэлементный шаблон, экземпляры self могут использоваться в качестве констант. Это относится к классу Color, который определяет экземпляр для каждого из распространенных цветов.
http://docs.oracle.com/javase/7/docs/api/java/awt/Color.html
Ответ №3:
Класс Android Service
(sub) не может быть одноэлементным, поскольку для фреймворка требуется доступ к конструктору по умолчанию для класса. Единственная причина, которую я могу придумать для сохранения статической ссылки на (последний) экземпляр, для которого onStart
был вызван, — это упростить некоторый внутренний код, который может находиться в статических методах.
Учитывая, что onStart
это устарело давным-давно (начиная с уровня API 5), это, скорее всего, пример плохого стиля кодирования с первых дней Android.
Комментарии:
1. Да, это тоже было бы моим предположением. Где-то в этом сервисе есть / есть статические методы, поэтому, чтобы иметь возможность доступа к экземпляру сервиса, его следует сделать статическим. Действительно некрасиво, и это не имеет никакого смысла в случае управляемых компонентов Android.
Ответ №4:
Чтобы другие классы могли получать экземпляр и вызывать методы экземпляра для объекта. Он часто используется с одноэлементным шаблоном. А для сервисов и действий в Android это очень плохая идея — он сохраняет ссылку на Activity / Service после его завершения, что приведет к утечке памяти.
Ответ №5:
В небезопасной для потоков реализации одноэлементного шаблона у вас будет частный конструктор и public static getInstance
метод, при необходимости инициализирующий этот экземпляр и возвращающий его.
Вот пример. Обратите внимание, что рекомендуется использовать товар одноэлементного перечисления вместо приведенного ниже кода, чтобы получить «истинный» синглтон.
public class MyThreadUnsafeSingleton {
private static MyThreadUnsafeSingleton instance;
private MyThreadUnsafeSingleton() {
//TODO some ctor logic
}
public static MyThreadUnsafeSingleton getInstance() {
if (instance == null) {
instance = new MyThreadUnsafeSingleton();
}
return instance;
}
}
Последнее замечание, существует вариант вышеупомянутого шаблона, который является потокобезопасным для одного загрузчика классов за счет использования вложенного класса «holder», но это выходит за рамки.
Ответ №6:
Если у него есть частный конструктор по умолчанию, это, вероятно, одноэлементный.
Если это не так, это что-то странное.
Такой макет заставляет все экземпляры объектов этого класса обмениваться данными, независимо от того, когда они создаются. Экземпляр объекта, для которого вызывается OnStart, станет базовым источником данных для любых ссылок на этот класс, независимо от того, когда они были объявлены или созданы (до или после OnStart), и независимо от того, в каком потоке они были созданы.
Конечно, всегда возможно, что есть члены класса, которые не беспокоятся о важности.Член и используйте это.Вместо этого член. Такое смешивание и сопоставление, вероятно, в конечном итоге приведут к катастрофическим последствиям.
Трудно представить конкретное применение для этого, но я предполагаю, что класс представляет собой абстракцию некоторого ресурса с отслеживанием состояния, который является глобальным по отношению к процессу, например, форма / окно или клиент веб-службы, который кэширует свои учетные данные. Хотя может быть что угодно.
Если этот код был написан примерно в 2003-2005 годах (ранние дни c #) Я бы предположил, что это неаккуратная реализация синглтона — тогда это было в моде, поскольку шаблоны проектирования становились привычными, а Синглтон был примером во всех учебниках. Оказывается, это ужасный шаблон для внедрения зависимостей и насмешек, поэтому в наши дни этот шаблон используется не так часто.
Комментарии:
1. «Экземпляры синхронизируются при вызове метода OnStart» — нет никаких доказательств того, что здесь происходит какая-либо синхронизация.
2. Правда, на самом деле это не «синхронизация». Указатель на объект mInstance просто обновляется в одном месте, но используется всеми. Отредактировано.
Ответ №7:
Эта парадигма часто используется для объектов, которые тяжелы или медленно создаются, и требуется только один.
public class Server {
private static Server server = null;
// Stop them making their own.
private Server () {
// Heavyweight stuff.
}
public static Server getServer () {
if ( server == null ) {
// Heavy constructor.
server = new Server();
}
return server;
}
}
В многопоточной среде это обычно сочетается с одноэлементным шаблоном проектирования.