iOS设计模式——Category

什么是Category

Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的,在很多情形下Category也是比创建子类更优的选择。新添加的方法 同样也会被被扩展的类的所有子类自动继承。当知道已有类中某个方法有BUG,但是这个类是以库的形式存在的,我们无法直接修改源代码的时 候,Category也可以用于替代这个已有类中某个方法的实体,从而达到修复BUG的目的。然而却没有什么便捷的途径可以去调用已有类中原有的那个被替 换掉方法实体了。需要注意的是,当准备有Category来替换某一个方法的时候,一定要保证实现原来方法的所有功能,否则这种替代就是没有意义而且会引 起新的BUG。和子类不同的是,Category不能用于向被扩展类添加实例变量。Category通常作为一种组织框架代码的工具来使用。

Category的用途

1.      在不创建继承类的情况下实现对已有类的扩展。

2.      简化类的开发工作(当一个类需要多个程序员协同开发的时候,Category可以将同一个类根据用途分别放在不同的源文件中,从而便于程序员独立开发相应的方法集合)。

3.      将常用的相关的方法分组。

4.      在没有源代码的情况下可以用来修复BUG。

Category的用法

在Obj-C中,声明某一个已有类的Category扩展的方法如下:

  1. @interface ClassName (CategoryName)  
  2. -methodName1  
  3. -methodName2  
  4. @end  

上面的声明通常是在.h文件中,然后我们在.m文件中实现这些方法:

  1. @implementation ClassName (CategoryName)  
  2. -methodName1  
  3. -methodName2  
  4. @end  


我们创建一个iOS Single View Applciation名为CategoryExample。然后为创建一个NSString类的category扩展。 File->New->File然后选择 Cocoa Touch Objective-C category.命名为ReverseNSString.系统会自动生成一个固定格式ClassName+CategoryName的.h和.m文件。

声明Category

打开NSString+ReverseNSString.h文件,在里面添加如下代码:

  1. #import <Foundation/Foundation.h>  
  2. @interface NSString (ReverseNSString)  
  3. + (NSString*) reverseString:(NSString*)strSrc;  
  4. @end  

实现Category

NSString+ReverseNSString.m文件中实现reverseString方法:

  1. #import"NSString+ReverseNSString.h"  
  2. @implementationNSString (ReverseNSString)  
  3. + (NSString*)reverseString:(NSString*)strSrc;  
  4. {  
  5.     NSMutableString *reversedString =[[NSMutableString alloc]init];  
  6.     NSInteger charIndex = [strSrc length];  
  7.     while (charIndex > 0) {  
  8.         charIndex--;  
  9.         NSRange subStrRange =NSMakeRange(charIndex, 1);  
  10.         [reversedString appendString:[strSrcsubstringWithRange:subStrRange]];  
  11.     }  
  12.     return reversedString;  
  13. }  
  14. @end  


剩下的工作就是验证我们的Category了,在view中添加一个按钮ReverseString,并设置相应的action方法为 reverseString.在view上再添加一个label,命名为myString,默认值是”HelloCategory Design Pattern!”。点击按钮反转这个字符串。主要代码如下:

  1. -(IBAction)reverseString:(id)sender {  
  2.     NSString *test = [NSStringreverseString:_myString.text];  
  3.     _myString.text = test;     
  4. }  

代码组织

Category用于大型类有效分解。通常一个大型类的方法可以根据某种逻辑或是相关性分解为不同的组,一个类的代码量越大,将这个类分解到不同的文件中就显得越有用,每个文件中分别是这个类的某些相关方法的集合。

当有多个开发者共同完成一个项目时,每个人所承担的是单独的cagegory的开发和维护。这样就版本控制就更加简单了,因为开发人员之间的工作冲突更少了。

Category VS添加子类

并没有什么界限分明的判定标准来作为何时用Category何时用添加子类的方法的指导。但是有以下几个指导性的建议:

    1. 如果需要添加一个新的变量,则需添加子类。
    2. 如果只是添加一个新的方法,用Category是比较好的选择。

Category是什么?

      1. 相对于java,Category是一个全新的概念,它为我们提供了区别于继承的另外一种方法来对类进行扩展。我们可以向任何已有的类(可以是你自己创建的类,可以是Foundation中的类,也可以是第三方的API)添加成员函数来实现功能上的扩展(注:category只允许添加成员函数,不能添加数据成员),添加的函数可以访问类中所有的数据成员,该类的子类也将继承新添加的成员函数。

        如何定义一个Category?

        07_category

        这很像一个类的声明。不同的地方在于后面没有列出父类,并且在括号里面写了Categories的名称。分类的名字可以随便取,但是最好能表达出你在类目中包含的方法所要做的事。

        创建一个Category.

        例如我们想为之前定义的手机类(Phone)添加一个上网的功能,

        Add Category

        Add Category

        声明Category扩展的方法:

        实现Category扩展的方法

        然后在main.m中#import “Phone+Internet.h”即可调用扩展的surfingTheInternet方法.

        Category的使用场景:

        1. 当你在定义类的时候,在某些情况下(例如需求变更),你可能想要为其中的某个或几个类中添加方法。
        2. 一个类中包含了许多不同的方法需要实现,而这些方法需要不同团队的成员实现
        3. 当你在使用基础类库中的类时,你可能希望这些类实现一些你需要的方法。

        Category的局限性:

        1. Category可以访问原始类的实例变量,但不能添加变量,如果想添加变量,可以考虑通过继承创建子类。
        2. Category可以重载原始类的方法,但不推荐这么做,这么做的后果是你再也不能访问原来的方法。如果确实要重载,正确的选择是创建子类。
        3. 和普通接口有所区别的是,在分类的实现文件中可以不必实现所有声明的方法,只要你不去调用它。
原文地址:https://www.cnblogs.com/lisa090818/p/3311695.html