类簇在iOS开发中的应用

移动开发 iOS
类簇的本质其实是抽象工厂,类簇也可以有多个基类,如NSArray, NSMutableArray, 后者就是继承的前者。它对一些「大同小异」的问题,往往会有不错的效果。

类簇(class cluster)是一种设计模式,在Foundation Framework中被广泛使用,举个简单的例子

NSArray *arr = [NSArray arrayWithObjects:@"foo",@"bar", nil]; 
NSLog(@"arr class:%@", [arr class]); 
// output: __NSArrayI 
  • 1.
  • 2.
  • 3.

显然__NSArrayI是一个私有类,来看看这个类的头文件

@interface __NSArrayI : NSArray { 
    unsigned int _used; 

 
//... 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

可以看出__NSArrayI继承了NSArray。为什么要这么设计呢?拿NSNumber来举个例子,我们都知道NSNumber可以存储多种类型的数字,如Int/Float/Double等等,一种方式是把NSNumber作为基类,然后分别去实现各自的子类,像这样:

初看起来也没什么问题,但如果子类很多,像这样:

这对使用者来说显然不够方便,得记住这么多类。如果使用类簇,问题就变得简单了,把Number作为抽象基类,子类各自实现存取方式,然后在基类中定义多个初始化方式,像这样:

现在只需要记住一个类就可以了。NSNumber的初始化伪代码大概像这样:

- (id)initWithBool 

    return [[__NSCFBoolean alloc]init]; 

 
- (id)initWithLong 

    return [[__NSCFNumber alloc]init]; 

 
//... 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

在iOS项目中的应用

在开发app时经常会遇到表现和行为完全一样,但数据源不一样的情况。以花瓣app为例,同样是瀑布流,可能来自我喜欢的图片、某个画板下的图片、 某个用户的图片等等。如果为每一种表现方式都新建一个Controller,并且使用这个Controller来初始化,那么就会遇到最开始提到的问题: 子类太多,使用不便。这正好可以通过类簇来很方便地搞定。比如这样:

@implementation HBWaterfallViewController 
- (id)initWithLiked 

    return [[HBLikedViewController alloc]init]; 

 
- (id)initWithBoardID:(NSInteger)boardID 

    return [[HBBoardViewController alloc]initWithBoardID:boardID]; 

 
#pragma mark - 通用的方法 
 
- (PSUICollectionViewCell *)collectionView:(PSUICollectionView *)collectionView 
                    cellForItemAtIndexPath:(NSIndexPath *)indexPath 

    // ... 

 
// ... 
 
#pragma mark - 每个子类需要实现的方法 
 
- (void)fetchMoreData 

    NSAssert(NO, @"子类需要实现此方法"); 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

使用起来类似这样[[HBWaterfallViewController alloc]initWithBoardID:9527][[HBWaterfallViewController alloc]initWithLiked]。如果有新的DataSource,新加一个初始化方法即可,对于使用者来说,打开头文件,看下init开头的方法就行了。

再举个例子,现在很多应用需要同时兼顾iOS6和iOS7,在表现上需要为不同的系统加载不同的图片资源,最简单粗暴的方法就是各种if/else判断,像这样:

if ([[UIDevice currentDevice]systemMajorVersion] < 7) 

    /* iOS 6 and previous versions */ 

else 

    /* iOS 7 and above */ 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

不够优雅,可以使用类簇的思想来去掉if/else判断,把跟视图具体元素无关的代码放在基类,跟系统版本相关的代码拆成两个子类,然后在各自的类中加载相应的资源。

/* TestView.h */ 
@interface TestView: UIView 
 
/* Common method */ 
- ( void )test; 
 
@end 
 
/* TestView.m */ 
@implementation TestView 
 
+ (id)alloc 

    if ([self class]== [TestView class]) 
    { 
        if ([[UIDevice currentDevice] systemMajorVersion] < 7) 
        { 
            return [TestViewIOS6 alloc]; 
        } 
        else 
        { 
            return [TestViewIOS7 alloc]; 
        } 
    } 
    else 
    { 
        return [super alloc]; 
    } 

 
- ( void )test 
{} 
 
@end 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

这里alloc时并没有返回TestView类,而是根据系统版本返回TestViewIOS6TestViewIOS7

/* TestViewIOS6.m */ 
@implementation TestViewIOS6: TestView 
 
- (void)drawRect: (CGRect)rect 

    /* Custom iOS6 drawing code */ 

 
@end 
 
/* TestViewIOS7.m */ 
@implementation TestViewIOS7 
 
- (void)drawRect: (CGRect)rect 

    /* Custom iOS7 drawing code */ 

 
@end 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

小结

类簇的本质其实是抽象工厂,类簇也可以有多个基类,如NSArray, NSMutableArray, 后者就是继承的前者。它对一些「大同小异」的问题,往往会有不错的效果。

参考

【移动开发视频课程推荐】

责任编辑:闫佳明 来源: blog.leezhong
相关推荐

2011-08-17 14:20:21

IOS开发GraphicsCon

2011-08-19 17:44:01

2025-02-28 10:31:50

2009-12-29 14:58:31

WPF优点

2015-07-02 14:38:44

2011-08-24 13:56:12

Lua游戏

2010-06-28 18:21:36

UML类图设计

2012-02-13 14:22:22

MonoTouchiOS应用Visual Stud

2011-08-22 16:26:25

IOS开发Sqlite数据库

2011-05-11 10:02:37

iOS

2010-03-01 10:45:59

WCF集合类

2022-12-06 23:43:53

iOSCreateML应用

2013-07-29 05:11:38

iOS开发iOS开发学习类的'生命周期'

2015-03-18 09:29:12

iOS开发争议

2013-06-12 22:42:38

iOS7WWDCiOS开发者

2011-08-08 14:07:49

iPhone开发 字体

2021-09-17 09:30:57

鸿蒙HarmonyOS应用

2011-08-22 15:47:27

Oracle临时表存储过程

2011-08-29 17:27:47

HTML 5交互移动应用

2011-09-06 16:44:47

IOS应用SQLite
点赞
收藏

51CTO技术栈公众号