One of the challenges in switching to a new language is figuring out how design patterns adapt. Sometimes the language has built-in facilities for the pattern, or features that work-around what the pattern was designed to do in the first place.
In Python, for example, it is trivial to implement a Command Dispatch Pattern and a Singleton pattern is almost wholly unnecessary–just create a module and put
“”"This module implements the singleton pattern”"”
at the top and voilà! It is a “singleton” for all intents and purposes.
Changing over to Objective-C is no different. This series will be about implementing design patterns in Objective-C as I’ve come to need them in my iPhone development experience.
One of the very first design patterns that I found I needed to use was the Singleton Pattern. I needed singular, static objects that had some variables and built-in functionality.
Examples:
- A commander that controlled the execution of the program.
- A database manager.
- A sound manager (Apple has kindly started to provide for this in iPhone SDK 2.2, but it isn’t present in 2.1 forcing the use of AudioQueues and/or SoundEngine).
- A file processor
- etc, etc, etc.
Basically a great deal of the “engine” to my game needed to share a few variables and group functionality together, but I didn’t want multiple copies running around.
After some research, this is the pattern that I settled on:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @implementation Singleton + (Singleton *)instance { static Singleton *instance; @synchronized(self) { if(!instance) { instance = [[Singleton alloc] init]; } } return instance; } @end |
The singleton object can then be accessed with [Singleton instance].
Walking through this step at a time:
- Line 4
- Declares a static variable. If you come from a Java background, the placement of this is probably a little confusing: In C (and Objective-C and C++) a static local variable is retained between function calls (similar to how a Java class-level static variable is retained between multiple instances of the class).
Unlike Java, we don’t really have the same option for “static initialization,” so we are using a standard lazy-loading pattern.
- Line 6
- We want synchronization around the self object so that two [Singleton instance] calls don’t result in two independent copies of the object. Even if it is a single-threaded app, this sort of synchronization doesn’t have a huge speed penalty and is a good practice for future development.
- Line 7
- Check to see if the object is initialized already, if not we will then initialize it on Line 8
- Line 14
- Returns the created/preserved instance.
So long as everyone on your team recognizes that this object is a singleton, this pattern is simple and sufficient. It is possible to create more than one object (no private constructor or overloading init/alloc, so [[Singleton alloc] init] will happily create another object), but so long as everyone follows the convention there shouldn’t be any problems.
Other possible methods involve overloading alloc and/or init or using the XIB file for Dependency Injection.
Due to the + notation, people should naturally jump to the instance method and see that it is a Singleton before trying to alloc their own copy of the object. Thus, for most projects, I tend to think of this as the simplest and best approach in Objective-C.