Question

What is the purpose of use of a factory method in objective-c context?

I am a bit confused about the use of factory methods in objective-c? What is the usefulness of doing so?

What is an example of using factory method in objective-c?

A bit confused. Any explanation would help!

Was it helpful?

Solution

Objective-C does not have constructor methods that are available in other programming languages. Factory methods are essentially Objective C's constructor methods. They allow you to allocate memory for your object and initialize the values.

In your class, add methods with this pattern:

//Please follow Obj C naming conventions and name all init 
//methods "initWith" then desc
-(id)initWithString:(NSString*)str {
    if(self = [super init]) {
        _someProperty = str;
        _someOtherProperty = 0;
    } return self;
}

//Please follow Obj C naming conventions and name all factory 
//methods "myClassWith" then desc
+(instancetype)someClassWithString:(NSString*)str {
    return [[self alloc] initWithString: str];
}

//Pretty much every factory method should have a matching init method, and 
//only one init method should actually do the if(self = [super init] { /*do
//stuff*/ } return self;, the other init methods should call this one in some
//form or fashion

Then in main, you can do:

SomeClass *myVariableName = [SomeClass someClassWithString: 
    @"Init with me please"];

It saves you from having to do this:

SomeClass *myVariableName = [[SomeClass alloc] initWithString: 
    @"Init with me please"];

Or this:

SomeClass *myVariableName = [[SomeClass alloc] init];
[myVariableName mySetterMethod: @"Init with me please"];
[myVariableName setThatOtherProperty: 0];

OTHER TIPS

A factory method can be any class or instance method which returns a newly created and initialized object.

A "class factory method" in a more strict Objective-C context is any class method of a class Class whose name begins with class.., with its prefix stripped and first letter lowercased. Example for class Foo:

+(Foo*) fooWithParam:(NSDictionary*)param;

One reason to use class factory methods is for convenience. If you have a class Foo it may be created as follows in the usual way:

Foo* foo = [[Foo alloc] initWithParam:param];

A convenient class factory method may now be used as this:

Foo* foo = [Foo fooWithParam:param];

However, there are other reasons where a class factory method is useful:

Suppose for example that the initWithParam: method can fail. Then there is much confusion about how this should be handled: should one throw an exception within init? Or should one return nil? There is controversy debate about the right approach in the community. Both approaches have subtle issues, including memory leaks which can not be avoided.

Thus, the most reasonable approach in such a case would be to use a class factory method with an error parameter. Here, you would get a Foo object as follows:

NSError* error;
Foo* foo = [Foo fooWithParam:param error:&error];

Now, the rule is: If foo is nil, there was an error, and one can obtain detailed info about the error with the output parameter error:

if (foo) {
    ...
}
else {
    NSLog(@"Error: %@", error);
}

Typically, the implementation would look as below:

+ (Foo*) fooWithParam:(NSDictionary*)param error:(NSError**error) {
    if ([param count] < 1) {
        // invalid parameters
        if (error) {                 
            NSError* error = [NSError errorWithDomain:@"Foo" code:-1000 userInfo: ...];            
        }
        return nil;
    }
    return [[self alloc] initWithParam:param]; // won't fail
}

Another reason is to implement "class clusters". That basically means that a class factory method returns a subclass of the class. An example is the NSStream class.

The NSInputStream class has a class factory method:

+ (id)inputStreamWithFileAtPath:(NSString *)path;

This returns a specialized class of NSInputStream.


In the pre-era of ARC there is an important detail:

Objects returned from a class factory method are 'autoreleased'. In other words, the client receiving the object does not own it - and thus does not need to release it.

Nowadays, with ARC these details became blurred: you do not need to release those objects manually anyway. How and when the object gets actually released is also subject to compiler optimizations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top