首页 > 代码库 > 单一职责原则

单一职责原则

单一职责原则

单一职责原则(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>@interface NSObject (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>@implementation NSObject (Properties)#pragma runtime - 动态添加了一个属性,map属性static char mapDictionaryFlag;- (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]];    return NSSelectorFromString(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      =http://www.mamicode.com/ nil;            id tmpValue   =http://www.mamicode.com/ dataDic[attributeName];                        if([tmpValue isKindOfClass:[NSNull class]])            {                // 如果是NSNull类型,则value值为空                value =http://www.mamicode.com/ 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);        return propertyNames;}// 根据属性数组获取该属性的值- (NSDictionary*)propertiesAndValuesDictionary:(id)obj properties:(NSArray *)properties{    NSMutableDictionary *propertiesValuesDic = [NSMutableDictionary dictionary];        for (NSString *property in properties)    {        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;        }    }        return propertiesValuesDic;}// 根据map值替换掉键值- (NSDictionary *)mapDictionary:(NSDictionary *)map dataDictionary:(NSDictionary *)data{    if (map && data)    {        // 拷贝字典        NSMutableDictionary *newDataDic = [NSMutableDictionary dictionaryWithDictionary:data];                // 获取所有map键值        NSArray *allKeys                = [map allKeys];                for (NSString *oldKey in allKeys)        {            // 获取到value            id value =http://www.mamicode.com/ [newDataDic objectForKey:oldKey];                        // 如果有这个value            if (value)            {                NSString *newKey = [map objectForKey:oldKey];                [newDataDic removeObjectForKey:oldKey];                [newDataDic setObject:value forKey:newKey];            }        }                return newDataDic;    }    else    {        return data;    }}@end

以下再来说说为什么有些方法是那么设计的。

因为是在category中,这个obj是可以替换成self而不用传递任何参数的,但为何还要单独写一个方法来传递obj参数呢?其实道理很简单,如果写成self后可以去掉obj参数,但是呢,这个方法就仅仅限于这个category中使用了,如果你想在其他的地方使用这个方法,你就得修改这个方法并重新弄一个方法,明显,这个方法并不是最基本不依赖于其他类的方法,就比如本例子中category的self,就是它依赖的目标,只有写成支持任意对象时才能算一个符合单一职责原则的方法。

所以,就在公开的方法中调用这个方法,将self传递给obj即可。

你仔细查看我写的没有公开的私有方法中,每一个方法都是可以复制粘贴拿到其他类里面直接使用的,它不依赖于任何的外部条件,仅仅是提供一个接口,你提供合适的参数,他就能给你想要的结果。

单一职责原则的核心就是代码可复用性最强,要将类、方法拆分成最小不可拆分单元,仅此而已哦,很简单:)

 

 

 
 
 

单一职责原则