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

Метод Singleton Instance vs Class

В последнее время, работая с Objective-C и различными написанными в нем библиотеками, я заметил два действительно популярных одноэлементных паттерна. Одна версия извлекает экземпляр singleton и вызывает его методы экземпляра, а другая версия предоставляет только методы класса и никогда не дает вам экземпляр для работы. Все имеют целью абстрагировать доступ к одному ресурсу (StoreKit, CoreData, Parse API и т.д.). Например, здесь используется прежний подход, используемый в MKStoreKit:

// initialize singleton during app boot
[MKStoreManager sharedManager]

// sometime later in the app
[[MKStoreManager sharedManager] buyFeature:kFeatureAId 
                                onComplete:^(NSString* purchasedFeature)
 {
     NSLog(@"Purchased: %@", purchasedFeature);
 }
                               onCancelled:^
 {
     NSLog(@"User Cancelled Transaction");
 }];

или, альтернативно, NSUserDefaults, UIApplication и т.д. Другой подход можно увидеть в MagicalRecord или здесь с Parse API:

// configure API credentials sometime during app boot
[Parse setApplicationId:@"123456"
              clientKey:@"123456"];

// sometime later
PFObject *testObject = [PFObject objectWithClassName:@"TestObject"];
[testObject setObject:@"bar" forKey:@"foo"];
[testObject save];

Каковы некоторые плюсы и минусы двух подходов и одна из них принципиально лучше, чем другая?

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

Спасибо!

4b9b3361

Ответ 1

Существует два разных способа реализации подхода, основанного на методах класса:

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

Последствия первой реализации заключаются в том, что все, что вы можете сделать с помощью singleton, вы можете сделать со скрытым singleton:

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

Если вы идете для реализации, которая не использует синглтон, вы будете полагаться на статические переменные, чтобы сохранить текущее состояние. Это законный выбор, но шаблон инициализации становится другим (возможно, даже с помощью dispatch_once), вы не можете переключать реализацию в середине, не полагаясь на некоторые уродливые условия if, и использование подкласса становится намного более сложным.

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

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

Ответ 2

Одно из преимуществ одноэлементного подхода состоит в том, что становится тривиальным, позволяя другим экземплярам, ​​если вам нужно. Если вы примете подход метода класса, все, что вы получите без большого количества рефакторинга.