The Factory pattern is a frequently used creational pattern to help abstract the creation of an object from its clients. Although there are a few specializations of this pattern I’ll focus on the most commonly used approach and then look at how we can leverage the Objective-C Runtime to make this solution more robust.
Let’s begin by creating a simple command-line app that creates Animal objects and gets them to speak on command. The various animal objects will all inherit from the abstract Animal class.
|
1 2 3 4 5 6 7 |
@interface Animal : NSObject { } - (void)speak; - (NSString *)key; @end |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@implementation Animal - (void)speak { NSAssert(NO, @"The 'speak' method must be implemented by subclass."); } - (NSString *)key { // Animal instances will be 'keyed' by their lower case class name // Overly simplistic, but will suffice for now return [NSStringFromClass([self class]) lowercaseString]; } @end |
With the abstract base class complete let’s create a couple concrete Animal implementations:
|
1 2 3 4 5 |
@implementation Cat - (void)speak { NSLog(@"Meow, Meow..."); } @end |
|
1 2 3 4 5 |
@implementation Dog - (void)speak { NSLog(@"Bark, Bark..."); } @end |
Our Cat & Dog objects are ready to go so let’s integrate them into our app and get them to speak.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Animal *cat = [[Cat alloc] init]; [cat speak]; [cat release]; Animal *dog = [[Dog alloc] init]; [dog speak]; [dog release]; [pool drain]; return 0; } |
Running this app will produce the following console output:
|
1 2 |
Meow, Meow... Bark, Bark... |
This works as we’d expect, but the main problem with using the Cat and Dog classes this way is coupling. Even though we’ve defined our variables as abstract Animal types we’re still coupled to the specific subtypes. This means we can’t modify our Animal types or evolve their creation without impacting our client code. This may seem like a trivial matter in this example, but these design decisions can have major impacts on real-world applications. Let’s avoid some of the potential ripple effects by introducing a factory.
Creating Animals
We’ll begin by moving the object creation responsibilities from our client to a new object called AnimalFactory. This factory, as you may have guessed, will be responsible for creating and vending instances of Animal. A simple, but common implementation of this could be defined as follows:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@implementation AnimalFactory + (AnimalFactory *)factory { return [[[[self class] alloc] init] autorelease]; } - (Animal *)animalForKey:(NSString *)animalKey { Animal *animal = nil; if ([animalKey isEqualToString:@"dog"]) { animal = [[Dog alloc] init]; } else if ([animalKey isEqualToString:@"cat"]) { animal = [[Cat alloc] init]; } else { NSAssert(NO, @"No Animal found for key:'%@'", animalKey); } return [animal autorelease]; } @end |
The AnimalFactory will determine which instance to create based on the argument passed to the animalForKey: method. It creates the appropriate instance and returns an autoreleased version of it to the client. To use this new factory in our client we can make the following changes:
|
1 2 3 4 |
AnimalFactory *factory = [AnimalFactory factory]; [[factory animalForKey:@"cat"] speak]; [[factory animalForKey:@"dog"] speak]; |
If you were to run this example again you would see the same output as before, but the introduction of this factory has helped us resolve two specific limitations in our previous implementation:
- The client is no longer coupled to a particular instance of
Animal. As our requirements change the factory can return alternate instances (FatCat,HotDog, etc.) without impacting our client code. - The client is no longer in the business of object creation which means how an animal is instantiated is no longer its concern. Additionally, by returning an autoreleased instance we don’t unnecessarily force memory management responsibilities onto the client.
One outstanding problem we have is with the factory itself. Although the client is better decoupled from the specific types and their creation, the factory itself is not. Every time we add a new animal to the app we additionally have to make modifications to the factory.
[Informercial Guy Voice] There’s got to be a better way!
Enter the Objective-C Runtime
Objective-C is a dynamic language where many decisions are deferred until runtime. This deferment allows for some of the more interesting capabilities of the language and is made possible through the Objective-C Runtime. Although you can successfully use Objective-C without having much awareness of the runtime, understanding how to interact with it can open up some interesting new possibilities.
It would be nice if our AnimalFactory could automatically find and dispense all instances of Animal without us having to continuously modify the factory. Thanks to the runtime, it can.
Automagic Factories
Let’s begin by creating a utility class called RuntimeUtils containing a method to allow us to dynamically find all instances of a particular type. This method will be implemented as follows:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
+ (NSArray *)classStringsForClassesOfType:(Class)filterType { int numClasses = 0, newNumClasses = objc_getClassList(NULL, 0); Class *classList = NULL; while (numClasses < newNumClasses) { numClasses = newNumClasses; classList = realloc(classList, sizeof(Class) * numClasses); newNumClasses = objc_getClassList(classList, numClasses); } NSMutableArray *classesArray = [NSMutableArray array]; for (int i = 0; i < numClasses; i++) { Class superClass = classList[i]; do { // recursively walk the inheritance hierarchy superClass = class_getSuperclass(superClass); if (superClass == filterType) { [classesArray addObject:NSStringFromClass(classList[i])]; break; } } while (superClass); } free(classList); return classesArray; } |
This method makes use of two functions defined in <objc/runtime.h>:
objc_getClassList– This function returns a list of all classes registered with the app. We’ll loop through this list and then filter its results.class_getSuperclass– Returns the superclass of a class. We recursively walk the inheritance hierarchy of each class to determine if it’s a descendant ofAnimal. If so, we add its class string to our array.
With our RuntimeUtils class now ready, let’s go back and revisit the implementation of our factory object.
Implementing the Magic
We’ll change the implementation of our factory class to leverage this new RuntimeUtils class. We’ll start by implementing the init method.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
- (id)init { if ((self = [super init])) { NSArray *animalClassStrings = [RuntimeUtils classStringsForClassesOfType:[Animal class]]; animals = [[NSMutableDictionary alloc] initWithCapacity:[animalClassStrings count]]; for (id classString in animalClassStrings) { Class animClass = NSClassFromString(classString); Animal *animal = [[animClass alloc] init]; [animals setObject:animal forKey:[animal key]]; [animal release]; } } return self; } |
Our init implementation starts by finding all the class strings for the classes extending Animal. We iterate through the results creating an instance of each class and storing its pointer in the animals dictionary. With the init method complete let’s modify the animalForKey: method.
|
1 2 3 4 5 |
- (Animal *)animalForKey:(NSString *)animalKey { Animal *animal = [animals objectForKey:animalKey]; NSAssert(animal, @"No animal found. Invalid 'animalType' specified?"); return animal; } |
We now have a greatly simplified animalForKey: method. Gone are the if/else or switch statements you’d typically see in a factory method. Instead, we have a simple, generic execution path regardless of the number of animals we add to the application.
To see the benefits of our revamped AnimalFactory, let’s make a couple additions to our animal kingdom.
|
1 2 3 4 5 |
@implementation Monkey - (void)speak { NSLog(@"Ooo, Ooo, Eee, Eee"); } @end |
|
1 2 3 4 5 |
@implementation Bird - (void)speak { NSLog(@"Tweet, tweet"); } @end |
We can go back to our client code and make the following changes:
|
1 2 3 4 |
[[factory animalForKey:@"dog"] speak]; [[factory animalForKey:@"cat"] speak]; <strong>[[factory animalForKey:@"monkey"] speak];</strong> <strong>[[factory animalForKey:@"bird"] speak];</strong> |
If you run the application again you’ll see the new Monkey and Bird instances were automatically registered with the factory without any additional changes! Winning!
Conclusion
Although this was clearly a contrived example, it hopefully illustrates how leveraging the Objective-C Runtime can result in significantly more flexible factory objects. Some simple modifications could be made to this approach to provide for lazy instantiation or handle more complex object creation. In a future post I’ll provide a more concrete example of how this strategy can be put to good use in a real-world application.
Resources
Sample Code
Objective-C Runtime Reference
Understanding the Objective-C Runtime

[ 13 comments ]
Shouldn’t that be NSLocalizedString(@”Meow, Meow…”, …)?
I was quite suprised how many different sounding spellings different languages have for common animal noises.
Seriously though, this was a nice article; I’d not used the runtime class enumeration to populate class factories before.
LOL. The funny thing is as I was writing this I remembered how my high school Spanish books had the dogs saying “Gah! Gah!”
Thanks!
Nice article Bob! It’s not always obvious how dynamic Objective-C is. It’s a lot more powerful than I’d first thought.
Very neat technique! Curious though why you decided to store an instance of each animal object in the factory instead of just creating a new one each time the animalForKey method was called?
No particular reason, just illustration. There are a number of valid variants that could be used that leverage this same basic technique. In fact, my actual production usage of this creates a new instance per invocation of the factory method.
I want to note that class objects are objects just like any other objects. So you can return an array of class objects themselves, instead of converting them to a string and then converting them back.
“We recursively walk the inheritance hierarchy of each class to determine if it’s a descendant of Animal.”
If you assume that the classes all descend from NSObject, then you can use the class method +isSubclassOfClass: to determine if it’s a descendant of Animal (since Animal is technically a subclass of itself, you would manually test for equality to Animal to exclude it if that’s what you want)
This is a real help Bob, thank you for writing this up.
Would there be any way to do this while the program is running e.g. automagic instantiation of runtime defined classes?
Ho Bob,
First of all, thanks for the great post!
Is there a solution for realloc(classList, sizeof(Class) * numClasses); under ARC ?
Ryno,
I think you just need to perform an explicit cast:
classList = (Class *)realloc(classList, sizeof(Class) * numClasses);
Thanks for post. Do I get it right, every time the factory is initiated, you alloc instances of all classes that factory can return? So if I ask factory to give me bird twice for same factory, it will return same class instances? May be it’s just simple example, for demonstrating, but isn’t it better to store just classes in animals(animalClasses) array, and for every animalForKey call return newly allocated class? Or maybe if I need same class every time, make factory a singleton…
The example isn’t meant to be prescriptive for how to implement your factory; that’s up to you. It’s just an illustration of how you can use the Objective-C runtime to add flexibility to your designs.
bear with me if this is a bad question, but why is
numClasses = newNumClasses;
classList = realloc(classList, sizeof(Class) * numClasses);
newNumClasses = objc_getClassList(classList, numClasses);
placed within that ‘while’ statement? Doesn’t it execute only once anyway? Is there a difference between the way its currently written and just removing the ‘while’?
thanks!
This was Apple’s documented way of retrieving the list of loaded classes in the current process. My understanding was multiple iterations were needed when loading code from a framework. See here: http://opensource.apple.com/source/objc4/objc4-208/runtime/objc-runtime.h
I had originally used this snippet in a Mac app I had written a while back. It’s possible that this was never necessary in an iOS app, but I’m not sure.