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中即可。代码的改动非常少,基本上符合开闭原则。

上一篇下一篇

猜你喜欢

热点阅读