设计模式来处理类似的方法

时间:2013-01-08 10:10:36

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

我的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。但是,尝试将这些方法组合到一个方法中会引入一些复杂性,这些复杂性会使每个方法的作用有些模糊。

有人能以最优雅的方式提供建议,以实现两种方法所包含的功能吗?保持这两种方法?创建一个更复杂的方法,撒上条件?打破另一个班级?

他们是这种情况的相关设计模式吗?感谢。

4 个答案:

答案 0 :(得分:1)

我建议:

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

  2. 对于每个公共块,定义一个获取正确参数并执行它们所需要的方法;

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

    <getInstances>
    <for each instance>
       <extract data from instance>
       <do your processing on data>
    
  4. 我不会考虑设计模式,而是考虑在这种情况下的重构。 你当然可以将所有这些封装在它自己的类中,但是我不知道当前包含你的代码的类所起的作用,所以我不能说更详细的内容。

    BTW,我倾向于在更高的抽象层次上使用设计模式(这就是为什么它们被称为设计模式,尽管许多在建筑层面上最有用)。在这种情况下,我认为一些重构配方(你可能会发现谷歌搜索)更适合。

答案 1 :(得分:1)

我会考虑Template design pattern

它基本上封装了基类中模板方法的基本行为,并且在基础子类中实现了conrete行为,这些子类实现(或覆盖)基类中定义的抽象方法。

有趣的资源也在SO上:Objective-C - Template methods pattern?

答案 2 :(得分:0)

我对Xcode并不擅长,所以让我只写一些逻辑。

在我看来,您的第二种方法可以通过以下方式简化:

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

您可能有兴趣阅读Facade Design Pattern

答案 3 :(得分:0)

使用设计模式访客或命令。这使您可以取消对要采取的操作的响应的提取和迭代。

这里有两件事:准备+循环+编组步骤和处理步骤。一部分是相同的(前者),一部分是变化的(后者)。所以你想要考虑后者,所以你可以避免制作前者的几个副本。

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

这一切都归结为您是否要使用继承或组合。就个人而言,我倾向于喜欢构图。