【问题标题】:Design pattern to deal with similar methods处理类似方法的设计模式
【发布时间】:2012-12-22 03:57:43
【问题描述】:

我的objective-c 类中有两个方法可以做类似但不同的事情。 (他们都检索一组包含 JSON 的核心数据记录,解压缩并检查 JSON 文档,并根据 JSON 的结构做一些事情)。

第一种方法如下:

+(NSDictionary*)getListOfResponsesWithForm:(NSString*)formId
{
    NSError* requestError = nil;

    // NSIndexSets don't allow easy targetted access into the set, so use arrays instead.
    NSMutableArray* indexSetOfAllEntries = [[NSMutableArray alloc] init];
    NSMutableArray* indexSetOfEntriesForLoggedOnUser = [[NSMutableArray alloc] init];

    NSString* activeUserEmail = getActiveUser().email;


    NSFetchRequest* fetchRequest = [ [NSFetchRequest alloc] init];

    NSEntityDescription* entityDesc = [NSEntityDescription entityForName:@"Response" inManagedObjectContext:getApp().managedObjectContext];

    [fetchRequest setEntity:entityDesc];

    // Sort by lastmodifieddatelocal
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"lastmodifieddatelocal" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    NSArray* instances = [getApp().managedObjectContext executeFetchRequest:fetchRequest error:&requestError];

    NSMutableArray* responses = [[NSMutableArray alloc] init];

    for (Response* response in instances) {


        NSData *jsonData = [response.json dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary* dictionary = [HPSJSON getDictionaryFromDataWithoutSuccessTest:jsonData];

        NSString* userEmailFromResponse = [HPSJSON getStringForKey: @"_useremail" inDictionary:dictionary];

        NSString* formIdFromResponse =  [HPSJSON getNestedIdForKey: @"_formid" inDictionary: dictionary];

        if ([formId caseInsensitiveCompare:formIdFromResponse]==NSOrderedSame)
        {
            [responses addObject: response];

            [indexSetOfAllEntries addObject:[NSNumber numberWithInt:responses.count-1]];

            if ([activeUserEmail caseInsensitiveCompare:userEmailFromResponse]==NSOrderedSame)
            {
                [indexSetOfEntriesForLoggedOnUser addObject:[NSNumber numberWithInt:responses.count-1]];
            }

        }

    }

    NSMutableDictionary* results = [[NSMutableDictionary alloc] init];
    [results setObject:responses forKey:@"responses"];
    [results setObject:indexSetOfAllEntries forKey:@"allindexes"];
    [results setObject:indexSetOfEntriesForLoggedOnUser forKey:@"indexesforactiveuser"];

    return results;

}

第二种方法如下:

+(NSInteger)getCountOfResponsesWithForm:(NSString*)formId
{
    NSError* requestError = nil;

    NSString* activeUserEmail = getActiveUser().email;

    NSFetchRequest* fetchRequest = [ [NSFetchRequest alloc] init];

    NSEntityDescription* entityDesc = [NSEntityDescription entityForName:@"Response" inManagedObjectContext:getApp().managedObjectContext];

    [fetchRequest setEntity:entityDesc];

    NSArray* instances = [getApp().managedObjectContext executeFetchRequest:fetchRequest error:&requestError];

    NSInteger countOfResponses=0;

    for (Response* response in instances) {

        NSData *jsonData = [response.json dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary* dictionary = [HPSJSON getDictionaryFromDataWithoutSuccessTest:jsonData];

        NSString* userEmailFromResponse = [HPSJSON getStringForKey: @"_useremail" inDictionary:dictionary];

        NSString* formIdFromResponse =  [HPSJSON getNestedIdForKey: @"_formid" inDictionary: dictionary];

        if ([formId caseInsensitiveCompare:formIdFromResponse]==NSOrderedSame)
        {
            if ([activeUserEmail caseInsensitiveCompare:userEmailFromResponse]==NSOrderedSame)
            {
                countOfResponses++;
            }

        }

    }

    return countOfResponses;

}

这里的重复代码相当多,我觉得我在某种程度上滥用了DRY。然而,尝试将这些方法组合成一个方法会引入一些复杂性,这会在某种程度上混淆每个单独方法的作用。

任何人都可以就实现这两种方法所包含的功能的最优雅方式提供建议吗?坚持这两种方法?创建一种更复杂的方法?分到不同的班级?

它们是这种场景的相关设计模式吗?谢谢。

【问题讨论】:

    标签: objective-c oop design-patterns methods dry


    【解决方案1】:

    我建议:

    1. 识别公共块(例如,NSFetchRequest* fetchRequest...、NSEntityDescription* entityDesc);

    2. 为每个公共块定义一个获取正确参数并执行所需参数的方法;

    3. 调用这样的方法来改进 DRY,例如:

      <getInstances>
      <for each instance>
         <extract data from instance>
         <do your processing on data>
      

    在这种情况下,我不会考虑设计模式,而是考虑重构。 您当然可以将所有这些封装在一个自己的类中,但我不知道当前包含您的代码的类所扮演的角色,所以我不能说更详细的内容。

    顺便说一句,我倾向于在更高的抽象层次上使用设计模式(这就是为什么它们被称为 design 模式,尽管许多模式大多在架构层面有用)。在这种情况下,我认为一些重构配方(您可能会在谷歌上搜索它们)更适合。

    【讨论】:

      【解决方案2】:

      我会考虑Template design pattern

      它基本上将基本行为封装在基类中的模板方法中,具体行为在实现(或覆盖)基类中定义的抽象方法的底层子类中实现。

      有趣的资源也在这里:Objective-C - Template methods pattern?

      【讨论】:

        【解决方案3】:

        使用设计模式访问者或命令。这使您可以将获取和迭代响应与要采取的操作分离。

        这里有两件事:准备 + 循环 + 编组步骤和处理步骤。一部分相同(前者),一部分不同(后者)。所以你想把后者排除在外,这样你就可以避免制作多份前者的副本。

        您可以通过将处理步骤设置为在子类中重载的虚拟方法,或者通过传入可以执行该步骤的“某物”来实现。这个“东西”通常是命令或访问者。

        这一切都归结为您是要使用继承还是组合。我个人更喜欢作曲。

        【讨论】:

          【解决方案4】:

          我不擅长 Xcode,所以让我写一些逻辑来代替。

          在我看来,您的第二种方法可以简化为:

          int getCountOfResponsesWithForm(String a)
          {
              Dictionary dic  = getListOfResponsesWithForm(a);
              return dic.length();
          }
          

          您可能有兴趣阅读Facade Design Pattern

          【讨论】:

          • 你是绝对正确的。我没有那样实现它的原因是性能(计数可能非常高,在我看来,内存使用可能会不必要地以这种方式受到影响)。不过很好,谢谢。
          猜你喜欢
          • 2023-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多