Альтернатива Singleton в Objective-C для лучшего дизайна приложения - PullRequest
17 голосов
/ 06 мая 2011

Кажется, что в настоящее время в коде Objective-C используется 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 " во всех своих приложениях без прохождения через настройки. 1023 *

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

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

Ответы [ 4 ]

33 голосов
/ 06 мая 2011

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

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

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

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

33 голосов
/ 06 мая 2011

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

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

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

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

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

Итак, вы вернетесь и начнете передавать данные, а не искать их (раньше это называлось хорошим дизайном ОО, но теперь у него есть причудливое имя, например «Внедрение зависимости»).

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

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

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

Подведем итог и для тех, кто тл; др:

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

3 голосов
/ 06 мая 2011

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

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

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

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

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

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

1 голос
/ 15 января 2013

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

id<FlightsClient>

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

_flightsClient = [FlightsClient sharedInstance];

Недостатки:

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

Хороший способ - применить шаблон проектирования внедрения зависимостей.

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

Вот библиотека внедрения зависимостей: https://github.com/typhoon-framework/Typhoon

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