Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

While recently working with Objective-C and various libraries written in it, I've noticed two really popular singleton patterns. One version fetches the singleton instance and calls its instance methods and other version only exposes class methods and never gives you an instance to work with. All have the purpose of abstracting access to a single resource (StoreKit, CoreData, Parse API etc.). For example, here's the former approach used in 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");
 }];

or alternatively NSUserDefaults, UIApplication etc.. The other approach can be seen in MagicalRecord or here with 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];

What are some pros and cons of the two approaches and is one of them fundamentally better than the other?

Not having to retrieve the shared instance saves some screen estate (the performance difference is likely irrelevant), but am I screwing myself in some other way, for example, testability-wise?

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
318 views
Welcome To Ask or Share your Answers For Others

1 Answer

There are two different ways to implement the approach based on class methods:

  • Make a singleton instance using a class hidden from everybody, and hide its methods behind wrapper class methods with identical signatures, or
  • Make class methods that do all the work

The implications of the first implementation are that everything you can do with a singleton, you can do with the hidden singleton:

  • using a subclass becomes a possibility
  • switching the instance in the middle of the run is easy
  • the state lives in instance variables
  • initialization follows the familiar pattern

If you go for an implementation that does not use a singleton, you would be relying on static variables to keep your current state. That is a legitimate choice, but the initialization pattern becomes different (perhaps even using a dispatch_once), you cannot switch the implementation in the middle without relying on some ugly if conditions, and using a subclass becomes a lot more tricky.

Testing the first implementation is somewhat easier than testing the second one, because you can provide a separate implementation of the singleton for testing, perhaps through the back door; with a static-based implementation, this route cannot be taken.

To summarize, I would use a singleton-based solution, with the singleton optionally hidden behind a "facade" that provides access to singleton's methods. I would not use an implementation where all state must be placed in static variables.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...