Automagic Factories in Objective-C

by Bob McCune on April 8, 2011

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.

With the abstract base class complete let’s create a couple concrete Animal implementations:

Our Cat & Dog objects are ready to go so let’s integrate them into our app and get them to speak.

Running this app will produce the following console output:

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:

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:

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:

  1. 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.
  2. 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:

This method makes use of two functions defined in <objc/runtime.h>:

  1. 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.
  2. class_getSuperclass – Returns the superclass of a class. We recursively walk the inheritance hierarchy of each class to determine if it’s a descendant of Animal. 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.

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.

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.

We can go back to our client code and make the following changes:

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 ]

Tim Gogolin April 8, 2011 at 5:51 pm

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.

Bob McCune April 8, 2011 at 6:15 pm

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!

John Shields April 9, 2011 at 4:44 pm

Nice article Bob! It’s not always obvious how dynamic Objective-C is. It’s a lot more powerful than I’d first thought.

Paul Mans April 25, 2011 at 6:54 pm

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?

Bob McCune April 25, 2011 at 8:00 pm

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.

bob July 29, 2011 at 1:21 am

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)

Kevin January 3, 2012 at 5:35 pm

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?

Ryno July 11, 2012 at 8:17 am

Ho Bob,

First of all, thanks for the great post!

Is there a solution for realloc(classList, sizeof(Class) * numClasses); under ARC ?

Bob McCune July 11, 2012 at 11:22 am

Ryno,

I think you just need to perform an explicit cast:

classList = (Class *)realloc(classList, sizeof(Class) * numClasses);

Danich September 26, 2012 at 7:13 am

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…

Bob McCune September 26, 2012 at 6:42 pm

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.

seaney November 7, 2012 at 2:17 pm

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!

Bob McCune November 7, 2012 at 3:35 pm

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.