TestsTested | ✓ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Dec 2014 |
Maintained by Unclaimed.
TPFactory is a factory pattern implementation taking advantage of the Objective-C runtime to eliminate the need for header imports and long if statements.
Please let me know.
Add the following line to your podfile and install.
Check out CocoaPods for more information
pod "TPFactory", "~> 0.0.1"
Run pod install
in your project directory.
First of all, TPFactory is made up of two different implementations of how to detect classes that should exist in the factory.
TPSubclassFactory
Will add all subclasses that implements the TPBaseFactoryProtocol protocol of given class.
TPProtocolFactory
Will add all classes in the runtime which implements the specified protocol.
They both use a protocol TPBaseFactoryProtocol or deriviate to identify classes that should be in the factory. TPBaseFactoryProtocol is defined as following:
@protocol TPBaseFactoryProtocol <NSObject>
+ (NSInteger) priority;
+ (BOOL) canHandleObject: (id<NSObject>) object;
- (void) setObject: (id<NSObject>) object;
@end
@interface TPUser : TPModel
@end
@interface TPManager : TPUser
@end
@interface TPDeveloper : TPUser
@end
@interface TPUser : TPModel
@end
@interface TPManager : TPUser<TPBaseFactoryProtocol>
@end
@interface TPDeveloper : TPUser<TPBaseFactoryProtocol>
@end
and or implementations
User
@implementation TPUser
@end
Developer
@implementation TPDeveloper
+ (NSInteger) priority {
return 0;
}
+ (BOOL) canHandleObject: (id<NSObject>) object {
id value = nil;
if ( (value = [object isKindOfClass:[NSDictionary class]] ) ) {
return [[value objectForKey: @"role"] isEqualToString: @"developer"] );
}
return NO;
}
- (void) setObject: (id<NSObject>) object {
[self parseDictionary: object];
}
@end
Manager
@implementation TPManager
+ (NSInteger) priority {
return 1;
}
+ (BOOL) canHandleObject: (id<NSObject>) object {
id value = nil;
if ( (value = [object isKindOfClass:[NSDictionary class]] ) ) {
return [[value objectForKey: @"role"] isEqualToString: @"manager"] );
}
return NO;
}
- (void) setObject: (id<NSObject>) object {
[self parseDictionary: object];
}
@end
Now we have made our classes ready for the TPSubclassFactory type of factory. Lets create a instance of a subclass factory and use it.
// Create a instance of the factory with the TPUser class as the root class and default options
TPSubclassFactory *userFactory = [[TPSubclassFactory alloc] initWithClass: NSClassFromString(@"TPUser") andOptions: TPProtocolFactoryDefaultOptions];
// Create two dictionaries that we can test it out with
NSDictionary *fakeDeveloperDictionary = @{@"role":@"developer"};
NSDictionary *fakeManagerDictionary = @{@"role":@"manager"};
// Now create a instance with the developer dictionary
id<NSObject> developer = [userFactory createInstanceForObject:fakeDeveloperDictionary];
// Now create a instance with the manager dictionary
id<NSObject> manager = [userFactory createInstanceForObject:fakeManagerDictionary];
NSLog(@"Developer: %@", NSStringFromClass([developer class]));
NSLog(@"Manager: %@", NSStringFromClass([manager class]));
Would output:
User: TPDeveloper
Manager: TPManager
As the name implies instead of using subclasses to find which ones to add this will look for a specific protocol to add it also has another feature set to it.
@protocol TPUserFactoryProtocol <TPProtocolFactoryProtocol>
@end
@interface TPManager : TPUser<TPUserFactoryProtocol>
@end
@interface TPDeveloper : TPUser<TPUserFactoryProtocol>
@end
@interface TPGroup : TPModel<TPUserFactoryProtocol>
@property(nonatomic,strong) NSArray *users;
@end
and here comes the implementations:
Developer
@implementation TPDeveloper
+ (NSInteger) priority {
return 0;
}
+ (BOOL) canHandleObject: (id<NSObject>) object {
id value = nil;
if ( (value = [object isKindOfClass:[NSDictionary class]] ) ) {
return [[value objectForKey: @"role"] isEqualToString: @"developer"] );
}
return NO;
}
- (void) setObject: (id<NSObject>) object {
[self parseDictionary: object];
}
+ (NSInteger) factoryType {
return 1;
}
@end
Manager
@implementation TPManager
+ (NSInteger) priority {
return 1;
}
+ (BOOL) canHandleObject: (id<NSObject>) object {
id value = nil;
if ( (value = [object isKindOfClass:[NSDictionary class]] ) ) {
return [[value objectForKey: @"role"] isEqualToString: @"manager"] );
}
return NO;
}
- (void) setObject: (id<NSObject>) object {
[self parseDictionary: object];
}
+ (NSInteger) factoryType {
return 1;
}
@end
Group
@implementation TPGroup
+ (NSInteger) priority {
return 2;
}
+ (BOOL) canHandleObject: (id<NSObject>) object {
id value = nil;
if ( (value = [object isKindOfClass:[NSDictionary class]] ) ) {
return [[value objectForKey: @"role"] isEqualToString: @"group"] );
}
return NO;
}
- (void) setObject: (id<NSObject>) object {
// lets not do anything right now.
}
+ (NSInteger) factoryType {
return 1;
}
@end
So we now have our objects setup again. lets to a simple example on how to to use the factory this time as a singleton.
@interface TPObjectFactory : TPProtocolFactory
+ (id) shared;
@end
@implementation TPObjectFactory
TPPROTOCOLFACTORY_SINGELTON_DEFAULT(TPObjectFactory, @protocol(TPUserFactoryProtocol));
@end
#import "TPObjectFactory.h"
// Create two dictionaries that we can test it out with
NSDictionary *fakeDeveloperDictionary = @{@"role":@"developer"};
NSDictionary *fakeManagerDictionary = @{@"role":@"manager"};
NSDictionary *fakeGroupDictionary = @{@"role":@"group", @"users":@[fakeDeveloperDictionary,fakeManagerDictionary]};
// Now create a instance with the developer dictionary
id<NSObject> developer = [[TPObjectFactory shared] createInstanceForObject:fakeDeveloperDictionary];
// Now create a instance with the manager dictionary
id<NSObject> manager = [[TPObjectFactory shared] createInstanceForObject:fakeManagerDictionary];
// Now create a instance with the group dictionary
id<NSObject> group = [[TPObjectFactory shared] createInstanceForObject:fakeGroupDictionary];
NSLog(@"Developer: %@", NSStringFromClass([developer class]));
NSLog(@"Manager: %@", NSStringFromClass([manager class]));
NSLog(@"Group: %@", NSStringFromClass([group class]));
NSLog(@"Group users: %@", [group users]);
Would output:
User: TPDeveloper
Manager: TPManager
Group: TPGroup
Group users: nil
Lets now do some more stuff with this. Remember we didn't do anything with the group model. Thats about to change.
Group
#import "TPObjectFactory.h"
@implementation TPGroup
+ (NSInteger) priority {
return 2;
}
+ (BOOL) canHandleObject: (id<NSObject>) object {
id value = nil;
if ( (value = [object isKindOfClass:[NSDictionary class]] ) ) {
return [[value objectForKey: @"role"] isEqualToString: @"group"] );
}
return NO;
}
- (void) setObject: (id<NSObject>) object {
if ( [object isKindOfClass:[NSDictionary class]] ) {
id value = nil;
if ( (value = [object objectForKey:@"users"]) && [value isKindOfClass:[NSArray class]]) {
NSMutableArray *_users = [NSMutableArray arrayWithCapacity: [value count]];
for(NSDictionary *user in value) {
[_users addObject:[[TPObjectFactory shared] createInstanceForObject:user]];
}
[self setUsers:[_users copy]];
}
}
}
+ (NSInteger) factoryType {
return 1;
}
@end
Now our example above would output:
User: TPDeveloper
Manager: TPManager
Group: TPGroup
Group users: [<TPDeveloper 0x*****>,<TPManager 0x*****>]
Open a issue on Github.
TPFactory is available under the MIT license. See the LICENSE file for more info.