Выбор синглтона или категории? - PullRequest
5 голосов
/ 07 марта 2012

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

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

Итак, некоторое время спустя,Я решил переместить мою самую реализацию в категорию на UINavigationController (в конце концов, он обрабатывает переходы!), Сохранил исходные классы для сравнения, и мне интересно, какой метод будет работать лучше.Тщательно протестировав обе реализации, я могу без сомнения сказать, что они одинаковы во всех отношениях, включая скорость, точность, плавность, частоту кадров, использование памяти и т. Д. Так что из них «лучше» в смысле общей ремонтопригодности?

РЕДАКТИРОВАТЬ: прочитав хорошо написанные аргументы, которые вы все сделали, я решил использовать синглтон.@JustinXXVII выдвинул самый убедительный аргумент (ИМХО), хотя я считаю, что каждый ответ здесь одинаково достоин своих заслуг.Спасибо всем за ваше мнение, я проголосовал за все ответы на вопрос.

Ответы [ 6 ]

6 голосов
/ 27 марта 2012

Я считаю, что лучшим вариантом является использование категории.

Поскольку, если вы уже используете UINavigationController, не имеет смысла создавать новый класс, который будет управлять только переходом, как вы сказали: (after all, it handles transitions!)

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

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

3 голосов
/ 31 марта 2012

Я думаю, что реальный вопрос в «дизайне» (как вы сказали, оба кода работают нормально), и записав вашу проблему в простых предложениях, вы найдете ответ:

  • Цель singleton - иметь в вашем приложении только один экземпляр класса. Таким образом, вы можете делиться вещами между объектами. (один доступен для многих объектов)

  • состоит в расширении доступных методов до класса a . (доступно только для одного класса объектов! хорошо ... объекты из подклассов тоже)

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

Мое мнение таково, что то, чего вы хотите достичь, охватывается категорией, и, делая это, вы гарантируете, что только объекты, которые обращаются к этому методу, имеют право использовать его. При использовании шаблона синглтона любой объект любого класса может вызывать ваш синглтон и его методы (и ... он может работать, никто не знает, как для версии ОС n, но ваше приложение может быть сломано в версии n + 1).

3 голосов
/ 27 марта 2012

Я сделаю случай для одноэлементного объекта. Синглтоны используются повсюду UIKit и iOS. Одна вещь, которую вы не можете сделать с категориями, это добавить переменные экземпляра. В этом есть две вещи:

  1. Рабочие процессы MVC не допускают объектов с глубоким знанием других объектов
  2. Иногда вам просто нужно место для ссылки на объект, который на самом деле нигде не принадлежит

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

У меня обычно есть один синглтон-класс во всех моих проектах XCode, который используется для хранения «глобальных» объектов и выполнения повседневных вещей, которыми я не хочу обременять свой AppDelegate.

Примером может быть сериализация / архивация объектов и разархивирование / восстановление. Я должен использовать один и тот же метод в нескольких классах, я не хочу расширять UIViewController некоторым методом сериализации для записи и чтения произвольных файлов. Может быть, это только мои личные предпочтения.

Мне также может понадобиться быстрый способ поиска информации в NSUserDefaults, но я не хочу всегда писать [[NSUserDefaults standardUserDefaults]stringForKey:@"blah"], поэтому я просто объявлю метод в моем синглтоне, который принимает строковый аргумент.

До сих пор я не особо задумывался об использовании категории для этих вещей. Хотя одно можно сказать наверняка, я бы не стал создавать экземпляр нового объекта сто раз, чтобы выполнить одно и то же задание, когда у меня может быть только один живой объект, который останется рядом и позаботится обо мне. (Без обременения AppDelegate)

2 голосов
/ 30 марта 2012

Почему бы вам просто не создать базовый подкласс UIViewController и не расширить все ваши контроллеры представления из этого объекта?Категория не имеет смысла для этой цели.

2 голосов
/ 28 марта 2012

В этой реализации, для которой нет необходимости использовать Singleton, может вообще не быть разницы.Это не значит, что его нет.

Пластиковое ведро вмещает столько же воды, сколько металлическое ведро, и делает это так же хорошо.В этом аспекте, кажется, нет никакой разницы между ними.Однако, если вы попытаетесь транспортировать что-то очень горячее, пластиковое ведро может не справиться с этой задачей ..

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

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

Но если бы вы создали диспетчер данных, который содержал бы массив объектов, которые вы ТОЛЬКО хотите, чтобы они были доступны в одном месте, Категория не была бы дозадание.Это типичная задача Синглтона.Одиночные кнопки - это объекты одного экземпляра (и, если они сделаны статичными, доступны практически везде).Категории являются расширениями существующих классов и ограничиваются классом, который он расширяет.

Чтобы ответить на ваш вопрос;выберите категорию.

* Подкласс также может работать, но имеет свои плюсы и минусы

1 голос
/ 28 марта 2012

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

+ (MyClass*) sharedInstance
{
    static MyClass *instance = nil;
    if (instance == nil)  instance = [[MyClass alloc] init];
    return instance;
}

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

Дело в том, что это единственное требование к синглтону. Роль метода доступа заключается в том, чтобы гарантировать, что существует только один экземпляр, а не в том, что он обеспечит доступ к этому экземпляру из любого места. Это всего лишь побочный эффект паттерна, когда метод доступа является статическим, каждый может получить доступ к этому единственному объекту, не имея априорной ссылки (указателя) на него. К сожалению, этот факт широко используется программистами Objective C, и это приводит к путанице в дизайне и ненависти к шаблону синглтона, который вы упомянули. Но в общем-то, это не ошибка одиночного шаблона, а неправильное использование метода доступа.

Теперь вернемся к вашему вопросу: если вам не нужны статические / глобальные переменные в вашем пользовательском коде перехода (я полагаю, вам это не нужно), тогда ответ определенно идет на категории. В C ++ вы бы создали подкласс из некоторого родительского класса BaseTransition и реализовали бы свои настоящие методы рисования. В Objective C есть категории (что, на мой взгляд, является еще одним способом, который легко портит дизайн, но они гораздо удобнее), где вы можете добавлять пользовательские функции, даже обращаясь к переменным вашего хост-класса. Используйте их всякий раз, когда вы можете использовать синглтоны вместе с ними, и не используйте синглтоны, если главное требование к вашему классу не в том, чтобы это был только один его экземпляр.

...