工厂模式主要是为创建对象提供了接口,为了提高扩展性和维护性。分为三类:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
在以下情况下我们可以考虑使用工厂模式:
1.不能明确知道要创建哪种类的实例时。
2.系统不应依赖于产品类实例如何被创建、组合和表达的细节时。
简单工厂
工厂类+可快速创建对象的方法。
如下为了创建水果对象,定义个FruitsFactory工厂类,并定义一个创建对象的方法:
typedef NS_ENUM(NSInteger) {
kApple,
kOrange,
kBanana
} FruitsType;
@interface FruitsFactory : NSObject
+ (Fruits *)fruitsFactory:(FruitsType)type;
+ (Fruits *)fruitsFactory:(FruitsType)type {
Fruits *fruits = nil;
switch (type) {
case kApple:
fruits = [[Apple alloc] init];
break;
case kOrange:
fruits = [[Orange alloc] init];
break;
case kBanana:
fruits = [[Banana alloc] init];
default:
break;
}
return fruits;
}
定义水果对象抽象类,具体水果类继承它,并具体实现父类中抽象方法:
@interface Fruits : NSObject
- (void)sweet;
- (void)poorTaste;
@end
@implementation Fruits
- (void)sweet {}
- (void)poorTaste {}
@end
子类一:
@interface Apple : Fruits
- (void)freshApple; // 拓展了父类方法,开闭原则
@end
@implementation Apple
- (void)sweet {
NSLog(@"Apple 非常甜");
}
- (void)poorTaste {
NSLog(@"Apple 不好吃");
}
- (void)freshApple {
NSLog(@"Apple 新鲜的苹果");
}
@end
子类二:
@interface Orange : Fruits
- (void)acidOrange;
@end
@implementation Orange
- (void)sweet {
NSLog(@"Orange 非常甜");
}
- (void)poorTaste {
NSLog(@"Orange 不好吃");
}
- (void)acidOrange {
NSLog(@"Orange 有点酸");
}
@end
子类三:
@interface Banana : Fruits
@end
@implementation Banana
//具体实现父类中方法,里氏替换原则
- (void)sweet {
NSLog(@"Banana 非常甜");
}
- (void)poorTaste {
NSLog(@"Banana 不好吃");
}
@end
在viewController中使用:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 在水果工厂里面创建出苹果
Fruits *fruits = [FruitsFactory fruitsFactory:kApple];
[fruits sweet];
// 在水果工厂里面创建出苹果, 调用私有的方法
Apple *apple = (Apple *)[FruitsFactory fruitsFactory:kApple];
[apple freshApple];
// 在水果工厂里面创建出橘子, 调用私有的方法
Orange *orange = (Orange *)[FruitsFactory fruitsFactory:kOrange];
[orange acidOrange];
}
@end
工厂方法
对多个产品抽象,抽象出工厂类,其子类具体创建对应的对象:
@interface ColorViewGenerator : NSObject
- (ColorView *)colorViewWithFrame:(CGRect)frame;
@end
@implementation ColorViewGenerator
- (ColorView *)colorViewWithFrame:(CGRect)frame {
return [[ColorView alloc] initWithFrame:frame];
}
@end
子类一:创建RedView的工厂类
@interface RedViewGenerator : ColorViewGenerator
@end
@implementation RedViewGenerator
- (ColorView *)colorViewWithFrame:(CGRect)frame {
return [[RedView alloc] initWithFrame:frame];
}
@end
子类二:创建BlueView的工厂类
@interface BlueViewGenerator : ColorViewGenerator
@end
@implementation BlueViewGenerator
- (ColorView *)colorViewWithFrame:(CGRect)frame {
return [[BlueView alloc] initWithFrame:frame];
}
@end
抽象对象类:
@interface ColorView : UIView
@end
其两个子类:RedView和BlueView就可以通过相应的工厂方法创建了:
- (void)viewDidLoad {
[super viewDidLoad];
ColorViewGenerator *colorGen = [[RedViewGenerator alloc] init];
CGRect rect = CGRectMake(0, 0, 300, 600);
ColorView *red = [colorGen colorViewWithFrame:rect];
[self.view addSubview:red];
}
抽象工厂
抽象工厂是对工厂进行抽象。用意:给客户端提供一个接口,可以创建多个产品族中的产品对象。
例如上面的工厂方法例子中,如果视图又有两类:UIButton和UILabel,就可以使用抽象工厂来创建相应的对象。
比如红色视图工厂类中就可以定义两个方法:
@implementation RedViewGenerator
- (ColorView *)colorButtonWithFrame:(CGRect)frame {
return [[RedButton alloc] initWithFrame:frame];
}
- (ColorView *)colorLabelWithFrame:(CGRect)frame {
return [[RedLabel alloc] initWithFrame:frame];
}
@end
同理BlueViewGenerator
@implementation BlueViewGenerator
- (ColorView *)colorButtonWithFrame:(CGRect)frame {
return [[BlueButton alloc] initWithFrame:frame];
}
- (ColorView *)colorLabelWithFrame:(CGRect)frame {
return [[BlueLabel alloc] initWithFrame:frame];
}
@end
这样客户端通过调用RedViewGenerator的这两个方法就可以创建多个产品族的产品对象。其中RedButton和BlueLabel属于产品树,同理RedLabel和BlueButton也是,而RedButton和RedLabel属于产品族。
但是如果需要增加新的产品族比如textField,那么就要新增RedTextField和BlueTextField,相应的RedViewGenerator和BlueViewGenerator中要增加创建textField的方法,这样大批量的改动是很丑陋的做法。这里可以参见这篇文章
可以利用反射机制对抽象工厂模式进行优化。
如上图,两产品父类:BenzCar和BmwCar。分别有两sport和business子类,而工厂类中两方法的实现就使用了反射机制:
//利用反射机制优化抽象工厂。
@implementation Driver
- (BenzCar *)createBenzCarWithClassName:(NSString *)className{
return [[NSClassFromString(className) alloc] init];
}
- (BmwCar *)createBmwCarWithClassName:(NSString *)className{
return [[NSClassFromString(className) alloc] init];
}
使用就很方便了:
Driver *driver = [Driver new];
BenzSportCar *benzSportCar = (BenzSportCar *)[driver createBenzCarWithClassName:@"BenzSportCar"];
[benzSportCar drive];
BmwBusinessCar *bmwBusinessCar = (BmwBusinessCar *)[driver createBenzCarWithClassName:@"BmwBusinessCar"];
[bmwBusinessCar drive];
具体可参考代码Demo:反射机制优化抽象工厂
IOS中NSNumber就是一个工厂类。
NSNumber *num = [[NSNumber alloc] init];
NSNumber *intNum = [NSNumber numberWithInt:97];
NSNumber *floatNum = [NSNumber numberWithFloat:1.0f];
NSNumber *boolNum = [NSNumber numberWithBool:YES];
NSLog(@"num = %@",[[num class] description]);
NSLog(@"intNum = %@",[[intNum class] description]);
NSLog(@"floatNum = %@",[[floatNum class] description]);
NSLog(@"boolNum = %@",[[boolNum class] description]);
NSLog(@"转化 = %c",[intNum charValue]);
打印结果:
测试NSNumber抽象类[92463:6938499] num = (null)
测试NSNumber抽象类[92463:6938499] intNum = __NSCFNumber
测试NSNumber抽象类[92463:6938499] floatNum = __NSCFNumber
测试NSNumber抽象类[92463:6938499] boolNum = __NSCFBoolean
测试NSNumber抽象类[92463:6938499] 转化 = a