我的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。但是,尝试将这些方法组合到一个方法中会引入一些复杂性,这些复杂性会使每个方法的作用有些模糊。
有人能以最优雅的方式提供建议,以实现两种方法所包含的功能吗?保持这两种方法?创建一个更复杂的方法,撒上条件?打破另一个班级?
他们是这种情况的相关设计模式吗?感谢。
答案 0 :(得分:1)
我建议:
识别公共块(例如,NSFetchRequest * fetchRequest ...,NSEntityDescription * entityDesc);
对于每个公共块,定义一个获取正确参数并执行它们所需要的方法;
调用这种方法来改进DRY,例如:
<getInstances>
<for each instance>
<extract data from instance>
<do your processing on data>
我不会考虑设计模式,而是考虑在这种情况下的重构。 你当然可以将所有这些封装在它自己的类中,但是我不知道当前包含你的代码的类所起的作用,所以我不能说更详细的内容。
BTW,我倾向于在更高的抽象层次上使用设计模式(这就是为什么它们被称为设计模式,尽管许多在建筑层面上最有用)。在这种情况下,我认为一些重构配方(你可能会发现谷歌搜索)更适合。答案 1 :(得分:1)
它基本上封装了基类中模板方法的基本行为,并且在基础子类中实现了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)
使用设计模式访客或命令。这使您可以取消对要采取的操作的响应的提取和迭代。
这里有两件事:准备+循环+编组步骤和处理步骤。一部分是相同的(前者),一部分是变化的(后者)。所以你想要考虑后者,所以你可以避免制作前者的几个副本。
您可以通过使处理步骤成为在子类中重载的虚方法,或者通过传入可以执行该步骤的“某事”来实现。这个“东西”通常是命令或访客。
这一切都归结为您是否要使用继承或组合。就个人而言,我倾向于喜欢构图。