单一职责原则
单一职责原则(Simple responsibility pinciple SRP)
就一个类而言,应该仅有一个引起它变化的原因,如果你能想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。应该把多于的指责分离出去,分别再创建一些类来完成每一个职责。
单一职责原则是软件设计7大原则之一,其核心思想就是最大限度的提升代码的可复用性。
以下以具体的例子阐述,为何单一职责原则能最大限度的提升代码的可复用性。
之前写过一篇教程,教大家通过runtime扩展了NSObject的功能支持打印NSObject以及其子类的属性值以及进行字典直接赋值。
// //NSObject+Properties.h // //Created by YouXianMing on 14-9-4. //Copyright (c) 2014年 YouXianMing. All rights reserved. // #import <Foundation/Foundation.h> @interfaceNSObject (Properties) @property (nonatomic, strong) NSDictionary *mapDictionary; - (void)setDataDictionary:(NSDictionary*)dataDictionary; - (NSDictionary *)dataDictionary; @end
// //NSObject+Properties.m // //Created by YouXianMing on 14-9-4. //Copyright (c) 2014年 YouXianMing. All rights reserved. // #import "NSObject+Properties.h" #import <objc/runtime.h> @implementationNSObject (Properties) #pragma runtime - 动态添加了一个属性,map属性 static charmapDictionaryFlag; - (void)setMapDictionary:(NSDictionary *)mapDictionary { objc_setAssociatedObject(self, &mapDictionaryFlag, mapDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSDictionary *)mapDictionary { return objc_getAssociatedObject(self, &mapDictionaryFlag); } #pragma public - 公开方法 - (void)setDataDictionary:(NSDictionary*)dataDictionary { [self setAttributes:[self mapDictionary:self.mapDictionary dataDictionary:dataDictionary] obj:self]; } - (NSDictionary *)dataDictionary { //获取属性列表 NSArray *properties = [self propertyNames:[self class]]; //根据属性列表获取属性值 return[self propertiesAndValuesDictionary:self properties:properties]; } #pragma private - 私有方法 //通过属性名字拼凑setter方法 - (SEL)getSetterSelWithAttibuteName:(NSString*)attributeName { NSString *capital = [[attributeName substringToIndex:1] uppercaseString]; NSString *setterSelStr = [NSString stringWithFormat:@"set%@%@:", capital, [attributeName substringFromIndex:1]]; returnNSSelectorFromString(setterSelStr); } //通过字典设置属性值 - (void)setAttributes:(NSDictionary*)dataDic obj:(id)obj { //获取所有的key值 NSEnumerator *keyEnum =[dataDic keyEnumerator]; //字典的key值(与Model的属性值一一对应) id attributeName =nil; while ((attributeName =[keyEnum nextObject])) { //获取拼凑的setter方法 SEL sel =[obj getSetterSelWithAttibuteName:attributeName]; //验证setter方法是否能回应 if([obj respondsToSelector:sel]) { id value =nil; id tmpValue =dataDic[attributeName]; if([tmpValue isKindOfClass:[NSNull class]]) { //如果是NSNull类型,则value值为空 value =nil; } else { value =tmpValue; } //执行setter方法 [obj performSelectorOnMainThread:sel withObject:value waitUntilDone:[NSThread isMainThread]]; } } } //获取一个类的属性名字列表 - (NSArray*)propertyNames:(Class)class { NSMutableArray *propertyNames =[[NSMutableArray alloc] init]; unsigned int propertyCount = 0; objc_property_t *properties = class_copyPropertyList(class, &propertyCount); for (unsigned int i = 0; i < propertyCount; ++i) { objc_property_t property =properties[i]; const char *name =property_getName(property); [propertyNames addObject:[NSString stringWithUTF8String:name]]; } free(properties); returnpropertyNames; } //根据属性数组获取该属性的值 - (NSDictionary*)propertiesAndValuesDictionary:(id)obj properties:(NSArray *)properties { NSMutableDictionary *propertiesValuesDic =[NSMutableDictionary dictionary]; for (NSString *property inproperties) { SEL getSel =NSSelectorFromString(property); if([obj respondsToSelector:getSel]) { NSMethodSignature *signature =nil; signature =[obj methodSignatureForSelector:getSel]; NSInvocation *invocation =[NSInvocation invocationWithMethodSignature:signature]; [invocation setTarget:obj]; [invocation setSelector:getSel]; NSObject * __unsafe_unretained valueObj =nil; [invocation invoke]; [invocation getReturnValue:&valueObj]; //assign to @"" string if (valueObj ==nil) { valueObj = @""; } propertiesValuesDic[property] =valueObj; } } returnpropertiesValuesDic; } //根据map值替换掉键值 - (NSDictionary *)mapDictionary:(NSDictionary *)map dataDictionary:(NSDictionary *)data { if (map &&data) { //拷贝字典 NSMutableDictionary *newDataDic =[NSMutableDictionary dictionaryWithDictionary:data]; //获取所有map键值 NSArray *allKeys =[map allKeys]; for (NSString *oldKey inallKeys) { //获取到value id value =[newDataDic objectForKey:oldKey]; //如果有这个value if(value) { NSString *newKey =[map objectForKey:oldKey]; [newDataDic removeObjectForKey:oldKey]; [newDataDic setObject:value forKey:newKey]; } } returnnewDataDic; } else { returndata; } } @end
以下再来说说为什么有些方法是那么设计的。
因为是在category中,这个obj是可以替换成self而不用传递任何参数的,但为何还要单独写一个方法来传递obj参数呢?其实道理很简单,如果写成self后可以去掉obj参数,但是呢,这个方法就仅仅限于这个category中使用了,如果你想在其他的地方使用这个方法,你就得修改这个方法并重新弄一个方法,明显,这个方法并不是最基本不依赖于其他类的方法,就比如本例子中category的self,就是它依赖的目标,只有写成支持任意对象时才能算一个符合单一职责原则的方法。
所以,就在公开的方法中调用这个方法,将self传递给obj即可。
你仔细查看我写的没有公开的私有方法中,每一个方法都是可以复制粘贴拿到其他类里面直接使用的,它不依赖于任何的外部条件,仅仅是提供一个接口,你提供合适的参数,他就能给你想要的结果。
单一职责原则的核心就是代码可复用性最强,要将类、方法拆分成最小不可拆分单元,仅此而已哦,很简单:)