单一职责原则

摘要:
应该把多于的指责分离出去,分别再创建一些类来完成每一个职责。单一职责原则是软件设计7大原则之一,其核心思想就是最大限度的提升代码的可复用性。之前写过一篇教程,教大家通过runtime扩展了NSObject的功能支持打印NSObject以及其子类的属性值以及进行字典直接赋值。

单一职责原则

单一职责原则第1张

单一职责原则(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

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

单一职责原则第2张

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

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

单一职责原则第3张

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

单一职责原则第4张

单一职责原则第5张

单一职责原则第6张

单一职责原则第7张

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

免责声明:文章转载自《单一职责原则》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ViewModel中C# Property自动添加OnPropertyChanged处理的小工具, 以及相应Python知识点一些 NuGet 程序包是使用不同于当前目标框架的目标框架安装的,可能需要重新安装下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

OC常用数据类型大全解

UI基础OC常用数据类型 Block Block封装了一段代码,可以在任何时候执行 Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:block是inline(内联函数)的,并且默认情况下它对局部变量是只读的 苹果官方建议尽量多用block。在多线程、异步任务、集合遍历、集合排序、动画转场用...

ios-极光推送sdk使用

一、SDK导入 选择1:Cocoapods导入 pod 'JPush' 选择2:手动导入 1、在极光官网下载最新SDK 2、解压压缩包,将Lib下的所有文件复制到工程中 3、增加相关的framework依赖 CFNetwork.framework CoreFoundation.framework CoreTelephony.fra...

NSDictionary读取数据类型异常问题.

起因:做网络交互时,经常会使用JSON作为数据的承载体,本来是件好事,但是用多了,发现iOS侧偶尔会出现异常,几经比较发现是服务器给的数据有问题,该给INT的给按照STR给了,服务器能做动态更新,可客户端不行啊,怎么办?NSDictionary读到的是id类型,如果是数字,需要再转换下才可以,出问题就在这里.那解决思路就在这里,在这里增加判断实现用到了以下...

iOS 开发之照片框架详解(3)

http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 三. 常用方法的封装 虽然 PhotoKit 的功能强大很多,但基于兼容 iOS 8.0 以下版本的考虑,暂时可能仍无法抛弃 ALAssetLibrary,这时候一个比较好的方案是基于 ALAs...

ios 保存本地数据的方法

1。 NSString *path = [[NSBundle mainBundle] pathForResource:@"文件名" ofType:@"plist"]; // 文件数据类型是array NSArray *array=[NSArray arrayWithContentsOfFile:path]; //文件数据类型是*dictionary NSD...

&amp;lt;转&amp;gt;RestKit在iOS项目中的使用,包含xcode配置说明

本文转载至http://www.cnblogs.com/visen-0/archive/2012/05/03/2480693.html 最近在iPhone工程中添加RestKit并编译,但是由于之前找了很多不靠谱的说明文档,导致编译了一天也没有通过编译,总报出莫名其妙的错误。终于在最后的关头找了一篇英文的较为权威的文档才发现自己的问题出在一个很细节的地方。...