Guy Ephraim
Guy Ephraim

Reputation: 3520

Factory (design pattern) in Objective C

I'm trying to create a factory (design pattern) in Objective C So I'm doing something like:

+ (Car *)createCar:(int)color {
    if (color == 1) {
        return [CarFactory createBlueCar];
    } else if (color == 2) {
        return [CarFactory createRedCar];
    } else {
        return nil;
    }
}

+ (Car *)createBlueCar {
    // ...
}

+(Car*)createRedCar{
    // ...
}

However I don't want the createBlueCar and the createRedCar to be available to public and if I don't define them in the .h file then I get a warning of the missing definition.

I'm a former Java developer and a newbie in Objective-C — So it might be just bad practice If so what the be good practice of doing so.

Upvotes: 27

Views: 15717

Answers (3)

bbum
bbum

Reputation: 162722

The best way to do this is with a Class Extension.

.h

@interface MyClass : NSObject
@property(readonly) BOOL publiclyReadOnlyPrivatelyWritableFlag;
+ (id) myExposedFactoryMethod;
@end

.m

#import "MyClass.h"

@interface MyClass ()
@property(readwrite) BOOL publiclyReadOnlyPrivatelyWritableFlag;
+ (id) privateMethod1;
+ (id) privateMEthod2;
@end

@implementation MyClass
@synthesize publiclyReadOnlyPrivatelyWritableFlag; // no ivar -- only works in 64 bit and iPhone
+ (id) myExposedFactoryMethod
{
    ...
    [self privateMethod1];
    ...
}

+ (id) privateMethod1;
{
    return ...
}

+ (id) privateMEthod2;
{
    return ...
}
@end

A class extension is a better solution because it is a true extension of the class's interface whereas a category (without a corresponding implementation) is merely a suggestion that the class implement the methods. That is, the compiler will warn if you don't implement the interface -- the methods -- declared in the class extension, but will not warn if you did the same with a named category.

Note also that a class extension allows you to upgrade a readonly property to a readwrite property as per the above example.

Upvotes: 49

kennytm
kennytm

Reputation: 523764

You can create a private static function

@implementation Car 

static createBlueCar () {
  ....
}

+(Car*) createCar:(int) color{
   if (color==1) {
     return createBlueCar();
   } ...
}

@end

but no, you cannot create a true private member. (You can invoke some conventions e.g. +(Car*)private_createCar in a private category to discourage its use.)

Upvotes: -1

jkp
jkp

Reputation: 81330

I think you can add them to the class using an objective-c category within the implementation (not the interface) file as a way of emulating private methods if you want to "hide" them from users of your class.

Note, although you will no longer be advertising the methods to clients of your class, they will still be able to use them if they use the correct selectors. Additionally, they can always use something like classdump to regenerate the full interface to your class so your methods will never truly be hidden.

See this question for further examples of creating "private" methods under objective-c.

Upvotes: 4

Related Questions