iOS设计模式之工厂模式中(工厂方法)
2024-04-23 本文已影响0人
点滴86
工厂方法(Factory Method)
将简单工厂方法中的if分支逻辑去掉,比较经典的处理方法是利用多态,重构之后如下:
@protocol DMRuleConfigParserFactory <NSObject>
- (id<DMRuleConfigParser>)createParser;
@end
@interface DMJsonRuleConfigParserFactory : NSObject <DMRuleConfigParserFactory>
@end
@implementation DMJsonRuleConfigParserFactory
- (id<DMRuleConfigParser>)createParser
{
DMJsonRuleConfigParser *parser = [[DMJsonRuleConfigParser alloc] init];
return parser;
}
@end
@interface DMXmlRuleConfigParserFactory : NSObject <DMRuleConfigParserFactory>
@end
@implementation DMXmlRuleConfigParserFactory
- (id<DMRuleConfigParser>)createParser
{
DMXmlRuleConfigParser *parser = [[DMXmlRuleConfigParser alloc] init];
return parser;
}
@end
@interface DMPropertiesRuleConfigParserFactory : NSObject <DMRuleConfigParserFactory>
@end
@implementation DMPropertiesRuleConfigParserFactory
- (id<DMRuleConfigParser>)createParser
{
DMPropertiesRuleConfigParser *parser = [[DMPropertiesRuleConfigParser alloc] init];
return parser;
}
@end
这就是工厂方法模式的经典代码实现。当需要新增一种parser的时候,只需要新增一个实现了DMRuleConfigParserFactory协议的Factory类即可。所以,工厂模式比起简单工厂模式更加符合开闭原则。
从上面的工厂方法的实现来看,一切都很完美,但是实际上存在挺大的问题。问题在于这些工厂类的使用上。接下来,看一下,如何使用这些工厂类来实现DMRuleConfigSource的factoryMethod方法。代码如下:
@implementation DMRuleConfigSource
- (void)factoryMethod
{
NSString *filePath = @"";
NSString *fileExtension = [self getFileExtension:filePath];
id<DMRuleConfigParserFactory> parserFactory = nil;
if ([fileExtension isEqualToString:@"json"]) {
parserFactory = [[DMJsonRuleConfigParserFactory alloc] init];
} else if ([fileExtension isEqualToString:@"xml"]){
parserFactory = [[DMXmlRuleConfigParserFactory alloc] init];
} else if ([fileExtension isEqualToString:@"properties"]) {
parserFactory = [[DMPropertiesRuleConfigParserFactory alloc] init];
}
id<DMRuleConfigParser> parser = [parserFactory createParser];
NSString *fileContent = @"";
// 从配置文件中读取配置文本到fileContent中
DMRuleConfig *ruleConfig = [parser parse:fileContent];
}
/*
* 根据文件路径获取文件后缀,比如demo.json返回json
*/
- (NSString *)getFileExtension:(NSString *)filePath
{
return @"json";
}
@end
从代码实现来看,工厂类对象的创建逻辑有耦合进了factoryMethod方法中,引入工厂方法非但没解决问题,反倒让设计变得更加复杂了,该怎么解决这个问题呢?可以为工厂类在创建一个简单工厂,也就是工厂的工厂,用来创建工厂类对象。DMRuleConfigParserFactoryMap类是创建工厂对象的工厂类,+ (id<DMRuleConfigParserFactory>)getParserFactory:(NSString *)configStr方法返回的是缓存好的单例工厂对象,如下:
@interface DMRuleConfigParserFactoryMap : NSObject
+ (id<DMRuleConfigParserFactory>)getParserFactory:(NSString *)configStr;
@end
static NSMutableDictionary<NSString *, id<DMRuleConfigParserFactory>> *cachedFactories;
@implementation DMRuleConfigParserFactoryMap
+ (void)load
{
cachedFactories = [[NSMutableDictionary<NSString *, id<DMRuleConfigParserFactory>> alloc] init];
[cachedFactories setObject:[[DMJsonRuleConfigParserFactory alloc] init] forKey:@"json"];
[cachedFactories setObject:[[DMXmlRuleConfigParserFactory alloc] init] forKey:@"xml"];
[cachedFactories setObject:[[DMPropertiesRuleConfigParserFactory alloc] init] forKey:@"properties"];
}
+ (id<DMRuleConfigParserFactory>)getParserFactory:(NSString *)configStr
{
return [cachedFactories objectForKey:configStr];
}
@end
@implementation DMRuleConfigSource
- (void)factoryMethod
{
NSString *filePath = @"";
NSString *fileExtension = [self getFileExtension:filePath];
id<DMRuleConfigParserFactory> parserFactory = [DMRuleConfigParserFactoryMap getParserFactory:fileExtension];
id<DMRuleConfigParser> parser = [parserFactory createParser];
NSString *fileContent = @"";
// 从配置文件中读取配置文本到fileContent中
DMRuleConfig *ruleConfig = [parser parse:fileContent];
}
/*
* 根据文件路径获取文件后缀,比如demo.json返回json
*/
- (NSString *)getFileExtension:(NSString *)filePath
{
return @"json";
}
@end
当需要添加新的规则配置解析器的时候,只需要创建新的parser类和parserFactory类,并在DMRuleConfigParserFactoryMap类中,将新的parser factory对象添加到cachedFactories中即可。代码的改动非常少,基本上符合开闭原则。