zoukankan      html  css  js  c++  java
  • 单一职责原则

    单一职责原则

    单一职责原则(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      = 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);
        
        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 = [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即可。

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

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

     
     
     
  • 相关阅读:
    3.学习SpringMVC注解深入
    1.Google Blockly概述以及入门
    4.Servlet的Response和Request
    3.Servlet的ServletContext对象
    提高网络点击率的八种方法
    JNDI知道这么多就够了!
    jetty源代码剖析
    cocos2d-x 源代码分析 : control 源代码分析 ( 控制类组件 controlButton)
    Codeforces Round #254 (Div. 2)B. DZY Loves Chemistry
    几款“理想”“习惯”应用体验报告
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3963975.html
Copyright © 2011-2022 走看看