Objective-C Factory Methods: How to Do Them Wrong (and Right)

We all use factory methods, a.k.a. convenience methods. We often write them ourselves. But there’s a wrong way, and a right way, to write a factory method for your Objective-C class. Do it wrong, and you cut off some features of Objective-C. Do it right, and you open yourself up to new object-oriented possibilities.

Big [self alloc] factory

Volkswagen Factory Wolfsburg/Germany by Werner Kunz, used under CC BY-NC-SA 2.0 / Text added to original

Let’s back up and review what we mean by a factory method. This is a convenience method that you invoke on a class to say, “Make me one of your kind.” (Some folks call this a “convenience constructor” which is odd to me, because the underlying mechanics are quite different from Java or C++.)

Factory method: The wrong way

Let’s say we have a simple class:

@interface Foo : NSObject
- (id)init;

To create an autoreleased Foo object, we’d write

    Foo *aFoo = [[[Foo alloc] init] autorelease];

But if you do this a lot, it becomes tedious and can clutter your code. So let’s create a factory method.

At this point, it’s tempting to copy and paste into the body of the new method:

+ (Foo *)foo
    return [[[Foo alloc] init] autorelease];

Looks fine. Everything works. So what’s the problem?

Subclass trouble

In Java and C++, a class is a type. When you refer to a static method, you’re explicitly telling the compiler which method or function to use.

Not so in Objective-C.

Objective-C has its object-oriented roots in Smalltalk, where everything is an object. Even a class is an object. When you say [Foo alloc] you’re actually sending a runtime message to the Foo class, which decides what to do with that message.

Now let’s introduce a subclass:

@interface SpicyFoo : Foo

What happens if we send the earlier factory method to this subclass?

    SpicyFoo *aFoo = [SpicyFoo foo];

Ohh, we got trouble, right here in River City! Because it’s implemented the wrong way, the foo convenience method returns a new instance of Foo, not SpicyFoo — even though we were addressing the SpicyFoo class.

Factory method: The right way

Now let’s look at the right way to write a factory method. Then I’ll explain how it works, and why it’s important.

+ (id)foo
    return [[[self alloc] init] autorelease];

You may say, “Wait, isn’t this a class method? How can you have self in there?” Remember, classes are objects, too. Because this is a class method (as designated by the +), self refers to the class object:

  • If you send this message to a Foo, self is Foo.
  • If you send this message to a SpicyFoo, self is SpicyFoo.

So this solves the problem. No matter what the actual class is, the alloc will be sent to that class. With this new implementation, you can go ahead and send the message foo to SpicyFoo, knowing that the factory method will do the right thing and you’ll get a SpicyFoo instance back.

This also explains why we changed the return type to id: We don’t know what type of object it will return!

Here’s an important application of this pattern: when dealing with mutable and immutable variations, you can send a message to the superclass’s factory method. For example, NSDictionary declares a class method dictionary that returns a new dictionary instance. But you can do this:

    NSMutableDictionary *d = [NSMutableDictionary dictionary];

Even though dictionary is declared against NSDictionary, this returns a new instance of NSMutableDictionary, not NSDictionary.

Expanding beyond factory methods

So there’s a wrong way, and a right way, to write a factory method in Objective-C. Let’s continue to explore the right way, but expand it beyond factory methods.

Back to the Foo class, let’s add another class method — say, something that transforms an NSString:

@interface Foo : NSObject
+ (id)foo;
+ (NSString *)transformString:(NSString *)string;
- (id)init;

To invoke this class method from outside of Foo, you’d say

    NSString *transformed = [Foo transformString:original];

That’s all well and good. But what if you want to invoke it from within Foo itself? Once again, avoid the temptation to copy and paste.

From a class method, use

    NSString *transformed = [self transformString:original];

Remember, self in a class method refers to the class object.

From an instance method, use

    NSString *transformed = [[self class] transformString:original];

We avoid messaging the Foo class from Foo methods, whether they are class methods or instance methods. Why? Because we may be dealing with a subclass. Remember SpicyFoo, the subclass of Foo? By using this approach, SpicyFoo can provide its own implementation of +transformString:. Then code that messages self from a class method, or [self class] from an instance method, gives SpicyFoo the first crack at responding to the message.

Idiom: Don’t refer to your own class by name

Let’s boil it all down to a simple rule of thumb. In Objective-C, don’t refer to your own class by name, because you don’t know what the concrete class will be. You’ll inadvertently chop off the ability to extend and override the class through subclassing. Instead,

  • From a class method: message self
  • From an instance method: message [self class]

This is an Objective-C idiom. Applying this to factory methods, we come back to where we started:

  • To allocate an instance in a class’s factory method: [self alloc]

Go forth and self alloc!

Question: What other object-oriented patterns do we commonly overlook in Objective-C? Leave a comment below.

Did you find this useful? Subscribe today to get regular posts on clean iOS code.

About the Author Jon Reid

Jon is a coach and consultant on iOS Clean Code (Test Driven Development, unit testing, refactoring, design). He's been practicing TDD since 2001. You can learn more about his background, or see what services he can bring to your organization.

follow me on:

Leave a Comment:

Add Your Reply