美文网首页
iOS设计模式之工厂模式上(简单工厂)

iOS设计模式之工厂模式上(简单工厂)

作者: 点滴86 | 来源:发表于2024-04-21 22:58 被阅读0次

工厂模式

工厂模式(Factory Design Pattern)分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。

简单工厂(Simple Factory)

在代码示例中,根据配置文件的后缀(json、xml、properties),选择不同的解析器(DMJsonRuleConfigParser、DMXmlRuleConfigParser、DMPropertiesRuleConfigParser),将存储在文件中的配置解析成内存对象DMRuleConfig。

@protocol DMRuleConfigParser <NSObject>

- (DMRuleConfig *)parse:(NSString *)configStr;

@end

@interface DMJsonRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMJsonRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@interface DMXmlRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMXmlRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@interface DMPropertiesRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMPropertiesRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@implementation DMRuleConfigSource

- (void)sampleFactory
{
    NSString *filePath = @"";
    NSString *fileExtension = [self getFileExtension:filePath];
    id<DMRuleConfigParser> parser = nil;
    if ([fileExtension isEqualToString:@"json"]) {
        parser = [[DMJsonRuleConfigParser alloc] init];
    } else if ([fileExtension isEqualToString:@"xml"]){
        parser = [[DMXmlRuleConfigParser alloc] init];
    } else if ([fileExtension isEqualToString:@"properties"]) {
        parser = [[DMPropertiesRuleConfigParser alloc] init];
    }
    NSString *fileContent = @"";
    // 从配置文件中读取配置文本到fileContent中
    DMRuleConfig *ruleConfig = [parser parse:fileContent];
}

/*
 *  根据文件路径获取文件后缀,比如demo.json返回json
 */
- (NSString *)getFileExtension:(NSString *)filePath
{
    return @"json";
}

@end

为了让代码逻辑更加清晰,可读性更好,要善于将功能独立的代码块封装成函数。可以将代码中涉及parser创建的而部分逻辑玻璃出来,抽象成- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension函数。重构之后如下

@protocol DMRuleConfigParser <NSObject>

- (DMRuleConfig *)parse:(NSString *)configStr;

@end

interface DMJsonRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMJsonRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@interface DMXmlRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMXmlRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@interface DMPropertiesRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMPropertiesRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@implementation DMRuleConfigSource

- (void)sampleFactory
{
    NSString *filePath = @"";
    NSString *fileExtension = [self getFileExtension:filePath];
    id<DMRuleConfigParser> parser = nil;
    parser = [self createParser:fileExtension];
    NSString *fileContent = @"";
    // 从配置文件中读取配置文本到fileContent中
    DMRuleConfig *ruleConfig = [parser parse:fileContent];
}

/*
 *  根据文件路径获取文件后缀,比如demo.json返回json
 */
- (NSString *)getFileExtension:(NSString *)filePath
{
    return @"json";
}

- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension
{
    id<DMRuleConfigParser> parser;
    if ([fileExtension isEqualToString:@"json"]) {
        parser = [[DMJsonRuleConfigParser alloc] init];
    } else if ([fileExtension isEqualToString:@"xml"]){
        parser = [[DMXmlRuleConfigParser alloc] init];
    } else if ([fileExtension isEqualToString:@"properties"]) {
        parser = [[DMPropertiesRuleConfigParser alloc] init];
    }
    
    return parser;
}
@end

为了让类的职责更加单一、代码更加清晰,还可以进一步将- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension 方法剥离到一个独立的类中,让这个类只负责对象的创建。这个类就是简单工厂模式类。如下:

@protocol DMRuleConfigParser <NSObject>

- (DMRuleConfig *)parse:(NSString *)configStr;

@end

interface DMJsonRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMJsonRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@interface DMXmlRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMXmlRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@interface DMPropertiesRuleConfigParser : NSObject <DMRuleConfigParser>

@end

@implementation DMPropertiesRuleConfigParser

- (DMRuleConfig *)parse:(NSString *)configStr
{
    DMRuleConfig *ruleConfig = [[DMRuleConfig alloc] init];
    /*
     省略解析
     */
    return ruleConfig;
}

@end

@interface DMRuleConfigParserFactory : NSObject

- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension;

@end

@implementation DMRuleConfigParserFactory

- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension
{
    id<DMRuleConfigParser> parser;
    if ([fileExtension isEqualToString:@"json"]) {
        parser = [[DMJsonRuleConfigParser alloc] init];
    } else if ([fileExtension isEqualToString:@"xml"]){
        parser = [[DMXmlRuleConfigParser alloc] init];
    } else if ([fileExtension isEqualToString:@"properties"]) {
        parser = [[DMPropertiesRuleConfigParser alloc] init];
    }
    
    return parser;
}

@end

@implementation DMRuleConfigSource

- (void)sampleFactory
{
    NSString *filePath = @"";
    NSString *fileExtension = [self getFileExtension:filePath];
    id<DMRuleConfigParser> parser = nil;
    DMRuleConfigParserFactory *configParserFactory = [[DMRuleConfigParserFactory alloc] init];
    parser = [configParserFactory createParser:fileExtension];
    NSString *fileContent = @"";
    // 从配置文件中读取配置文本到fileContent中
    DMRuleConfig *ruleConfig = [parser parse:fileContent];
}

/*
 *  根据文件路径获取文件后缀,比如demo.json返回json
 */
- (NSString *)getFileExtension:(NSString *)filePath
{
    return @"json";
}

@end

在上面的示例代码中,每次调用DMRuleConfigParserFactory 的- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension 方法的时候,都会新创建一个parser。实际上,如果parser可以复用,为了节省内存和创建对象的时间,可以将parser事先创建好缓存起来。当调用- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension 方法的时候,直接从缓存中取出parser对象直接使用。代码如下:

static NSMutableDictionary<NSString *, id<DMRuleConfigParser>> *cachedParsers;

@implementation DMRuleConfigParserFactory

+ (void)load
{
    cachedParsers = [[NSMutableDictionary<NSString *, id<DMRuleConfigParser>> alloc] init];
    [cachedParsers setObject:[[DMJsonRuleConfigParser alloc] init] forKey:@"json"];
    [cachedParsers setObject:[[DMXmlRuleConfigParser alloc] init] forKey:@"xml"];
    [cachedParsers setObject:[[DMPropertiesRuleConfigParser alloc] init] forKey:@"properties"];
}

- (id<DMRuleConfigParser>)createParser:(NSString *)fileExtension
{
    id<DMRuleConfigParser> parser;
    parser = [cachedParsers objectForKey:fileExtension];
    
    return parser;
}

@end

对于上面两种简单工厂模式的实现方法。如果要添加新的parser,势必要改动DMRuleConfigParserFactory的代码,违反开闭原则。
除此之外,在DMRuleConfigParserFactory的第一种代码实现中,有一组if分支判断逻辑,是不是应该用多态或者其它设计模式来代替呢?实际上,如果if分支不是很多,代码中有if分支也是完全可以接受的。应用多态或者设计模式来代替if分支判断逻辑,也并不是没有任何缺点的,它虽然提高了代码的扩展性,更加符合开闭原则,但也增加了类的个数,牺牲了代码的可读性。

总结一下,尽管简单工厂模式的代码实现中,有多处if分支判断逻辑,违背开闭原则,但权衡扩展性和可读性,这样的代码实现在大多数情况下(比如,不需要频繁地添加parser,也没有太多的parser)是没有问题的。

相关文章

  • iOS设计模式(三)之抽象工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(一)之简单工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(二)之工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • 2016.06笔记

    iOS设计模式之工厂模式(简单工厂,工厂方法,抽象工厂) 简单工厂:简单工厂模式的工厂类一般是使用静态方法,通过接...

  • iOS设计模式之美-适配器模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • iOS设计模式之美-抽象工厂模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • iOS设计模式之美-工厂模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • iOS设计模式之美-生成器模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • iOS设计模式(3)适配器模式

    设计模式系列文章 《iOS设计模式(1)简单工厂模式》《iOS设计模式(2)工厂模式》《iOS设计模式(4)抽象工...

  • iOS设计模式(5)策略模式

    设计模式系列文章 《iOS设计模式(1)简单工厂模式》《iOS设计模式(2)工厂模式》《iOS设计模式(3)适配器...

网友评论

      本文标题:iOS设计模式之工厂模式上(简单工厂)

      本文链接:https://www.haomeiwen.com/subject/sprbxjtx.html