Подтвердить что ты не робот

Альтернатива Singleton в Objective-C для лучшего дизайна приложения

Кажется, что много кода Objective-C использует Singleton в настоящее время.

В то время как многие люди жалуются на Singleton, например. Google (Где все синглы ушли?), их коллеги-инженеры также используют его: http://code.google.com/mobile/analytics/docs/iphone/

Я знаю, что у нас уже есть ответы в Stack Overflow, но они не являются полностью специфичными для Objective-C как динамический язык: Objective C имеет категории, в то время как многие другие языки этого не делают.

Так что вы думаете? Вы все еще используете Singleton? Если да, то как сделать приложение более надежным?

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

В качестве примера можно использовать SDK Google Analytics iOS:

// Initialization
[[GANTracker sharedTracker] startTrackerWithAccountID:@"UA-0000000-1"
                                        dispatchPeriod:kGANDispatchPeriodSec
                                              delegate:nil];
// Track page view
[[GANTracker sharedTracker] trackPageview:@"/app_entry_point"
                                   withError:&error];

Красота вышеуказанного кода после инициализации с использованием метода " startTrackerWithAccountID", вы можете запускать метод " trackPageview" во всех своих приложениях, не проходя через конфигурации.

Если вы думаете, что Синглтон плохой, можете ли вы улучшить приведенный выше код?

Большое спасибо за ваш вклад, у вас счастливая пятница.

4b9b3361

Ответ 1

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

В iOS-разработке у вас есть один и только один экземпляр приложения, которое вы сейчас используете. Вы всего лишь одно приложение, верно? Вы не два или нулевые приложения, не так ли? Таким образом, инфраструктура предоставляет вам одноэлементный интерфейс UIApplication, через который можно получить функции os и framework на уровне приложений. Он моделирует что-то подходящее, чтобы быть синглом.

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

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

Ответ 2

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

Затем вы обнаружите, что модульное тестирование с помощью Singletons может быть затруднено. Вы фактически не хотите подключаться к базе данных, но ваш Синглтон делает. Добавьте слой перенаправления и издевайтесь над ним.

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

Затем какой-то другой код начинает возиться со значениями в вашем Singleton, пока вы его используете. Как они смеют! Если вы хотите, чтобы кто-нибудь мог получить эти значения из любого места, вы сделаете их глобальными...

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

Итак, вы возвращаетесь и начинаете передавать данные, а не просматриваете их (это раньше называлось хорошим дизайном OO, но теперь у него есть причудливое имя, например "Injection Dependency" ).

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

Итак, вы получаете общие объекты, такие как UIApplication и NSUserDefaults. Это хорошее применение синглтонов.

Я сгорел достаточно в увлечении Java Singleton десять лет назад. Я даже не рассматриваю возможность писать свои собственные синглтоны. Единственный раз, когда мне понадобилось что-то подобное в последней памяти, нужно кэшировать результат [NSCalendar currentCalendar] (что занимает много времени). Я создал категорию в NSCalendar и закрепил ее как статическую переменную. Я чувствовал себя немного грязно, но альтернативой был мучительно медленный код.

Подводя итог и для тех, кто tl; dr:

Синглтоны - это инструмент. Они вряд ли будут правильным инструментом, но вы должны это открыть для себя.

Ответ 3

Зачем вам нужен ответ "общая цель C"? Синглтоны также не являются полностью Obj-C, и вы можете их использовать. Функции не являются Obj-C-специфичными, целые числа не являются специфичными для Obj-C, и все же вы можете использовать все те, что содержатся в коде Obj-C.

Очевидные замены для singleton работают на любом языке.

Синглтон - плохо спроектированный глобальный.

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

Более тщательное решение, вместо того, чтобы иметь глобально доступный объект вообще, передать его как параметр для функций, которые ему нужны.

И, наконец, вы можете пойти на гибридное решение, используя инфраструктуру Injection Dependency.

Ответ 4

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

id<FlightsClient>

Обычный способ получить его в контроллере будет следующим:

_flightsClient = [FlightsClient sharedInstance];

Недостатки:

  • Трудно проверить класс отдельно.
  • Если вы хотите изменить клиента полета для другой реализации, его необходимо выполнить поиск в приложении и поменять его один за другим.
  • Если есть случай, когда приложение должно использовать другую реализацию (например, OnlineFlightClient, OfflineFlightClient), все становится сложным.

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

Подумайте об иждивенческой инъекции , рассказывая о архитектурной истории. Когда ключевые участники в вашем приложении подключаются к сборке, конфигурация приложений корректно модулярна (удаление дублирования). Создав этот script, его теперь легко переконфигурировать или обменять одного актера на другого ". Таким образом, нам не нужно сразу понимать всю проблему, ее легко развивать дизайн приложений по мере развития требований.

Здесь библиотека инъекций зависимостей: https://github.com/typhoon-framework/Typhoon