ios---类簇

我们都知道在iOS中类簇的使用是非常普遍的,比如 NSNumber 、 NSString NSArray 等等都是类簇。我们以 NSNumber 举例来说,对于int,bool, unsigned int 等等数据类型,我们如何把它们封装成类的形式呢? 通常情况下我们可能会想到,对于每一种数据类型独立封装成一个类,比如对于int 类型我们可以做一个NSInt的类,以此类推。这样想是正确的,但是,我们再来想想这样会有什么问题呢?当需要支持的数据类型越来越多时,这些类也会相应的越来越多,那么对于开发者来说,我们就需要记住越来越多的类。那么还有没有好的方案呢?哈哈,这个时候类簇就闪亮登场了。

现在我们遇到的问题是,相似的类越来越多,对于开发者来说需要太多的记忆。显然,我们解决问题的方向肯定是朝着减少暴露给开发者的类的数量这个方向。让我们来回忆一下设计模式,抽象工场模式不就是干这个事情的嘛!

对于 NSNumber ,我们使用一个 NSNumber 来作为int,bool,long等原生数据类型的工厂,对外定义一堆的工厂方法,在 NSNumber 内部则转调给相应的像 NSInt 这样的内部类去实现具体的逻辑。这样,我们遇到的问题就得到了完美的解决。

下面我们来自己实现一个具体的类簇。场景是这样的,我现在有一个App,只支持英文版,现在我想让其也支持中文版和日文版等等。 我们先来看看模型类吧!

@interface PowerUpDetail : WMModelObject

@property (nonatomic, copy)     NSString* name;
@property (nonatomic, copy)     NSString* desc;

@end

name 和 desc 分别是英文版对应的字段,现在我想实现中文版,并为以后的其他语言版本做好扩展结构。

现在有几个方案:

1.  继承PowerupDetail,实现子类PowerupDetailCN和PowerupDetailEN在所有调用PowerupDetail的地方,区分出到底应该调用PowerupDetailCN还是PowerupDetailEN。
2.  把PowerupDetail做成类簇,对外暴露通用接口,对内转调给内部类来实现具体逻辑。

方案1是最容易想到的,但是它的缺点是需要对已有的调用代码进行修改,而且如果将来随着越来越多的语言被支持,这些类将会非常多,在调用的地方需要一堆的if-else语句来区分,代码很丑,工作量很大。

方案2是比较好的一种方案,做到了对外暴露最小化,而所有调用的地方都可以不用修改,所有的修改可以只在PowerupDetail这个类中即可完成。

下面上代码~(≧▽≦)/~啦啦啦

在PowerUpDetail.h 文件中:

@interface PowerUpDetail : WMModelObject

@property (nonatomic, copy)     NSString* name;
@property (nonatomic, copy)     NSString* desc;

- (NSString *)localizedName;
- (NSString *)localizedDesc;

@end

在PowerUpDetail.m 文件中:

#pragma mark - For English Version
@interface _PowerUpDetailEN : PowerUpDetail
@end

@implementation _PowerUpDetailEN
@end

#pragma mark - For Chinese Version
@interface _PowerUpDetailCH : PowerUpDetail
@property (nonatomic, copy) NSString *nameCH;
@property (nonatomic, copy) NSString *descCH;
@end

@implementation _PowerUpDetailCH

- (instancetype)initWithDictionary:(NSDictionary *)dic
{
  if (self = [super initWithDictionary:dic]) {
    _nameCH = [[dic objectForKey:@"nameCH"] copy];
    _descCH = [[dic objectForKey:@"descCH"] copy];
  }
  return self;
}

- (NSString *)localizedName
{
  return self.nameCH;
}

- (NSString *)localizedDesc
{
  return self.descCH;
}

@end

#pragma mark - Class Cluster
@implementation PowerUpDetail

+ (instancetype)alloc
{
  if ([self class] == [PowerUpDetail class]) {
    if (WMIsChinesePreference) {
      return [_PowerUpDetailCH alloc];
    } else {
      return [_PowerUpDetailEN alloc];
    }
  } else {
    return [super alloc];
  }
}

- (instancetype)initWithDictionary:(NSDictionary *)dic
{
  if (self = [super initWithDictionary:dic]) {
    _name	   = [[dic objectForKey:@"name"] copy];
    _desc	   = [[dic objectForKey:@"desc"] copy];
  }
  return self;
}

- (NSString *)localizedName
{
  return self.name;
}

- (NSString *)localizedDesc
{
  return self.desc;
}

@end

这里,我实现了两个内部类 _PowerUpDetailCH 和 _PowerUpDetailEN ,他们都继承于 PowerUpDetail ,而 PowerUpDetail 暴露给外边两个方法:

    - (NSString *)localizedName;

    - (NSString *)localizedDesc;

这些方法可以在子类中按需要进行复写。

需要特别注意下类簇 PowerUpDetail 的alloc方法,这里要注意 if ([self class] == [PowerUpDetail class]) 这个条件的使用,否则会出现死循环,原因你应该很容易看出来,我就不啰嗦了!

+ (instancetype)alloc
{
  if ([self class] == [PowerUpDetail class]) {
    if (WMIsChinesePreference) {
      return [_PowerUpDetailCH alloc];
    } else {
      return [_PowerUpDetailEN alloc];
    }
  } else {
    return [super alloc];
  }
}

OK,我讲完了,类簇其实很简单,就是一个抽象工厂模式的iOS版本的实现。

时间: 2024-10-29 01:36:28

ios---类簇的相关文章

工厂设计模式的探讨——iOS类簇的应用分析

工厂设计模式的探讨--iOS类簇的应用分析 一.何为设计模式 什么是设计模式,先来看段度娘的话: 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 其实我们不需要这么专业,在我的理解,设计模式就是一种规范化的编程习惯,养成了这样的思想与习惯,

iOS 类簇(Class Cluster)使用心得

我们都知道在iOS中类簇的使用是非常普遍的,比如NSNumber.NSString.NSArray等等都是类簇.我们以NSNumber举例来说,对于int,bool, unsigned int 等等数据类型,我们如何把它们封装成类的形式呢? 通常情况下我们可能会想到,对于每一种数据类型独立封装成一个类,比如对于int 类型我们可以做一个NSInt的类,以此类推.这样想是正确的,但是,我们再来想想这样会有什么问题呢?当需要支持的数据类型越来越多时,这些类也会相应的越来越多,那么对于开发者来说,我们

iOS 8:【转】类簇在iOS开发中的应用

源地址:http://limboy.me/ios/2014/01/04/class-cluster.html 类簇(class cluster)是一种设计模式,在Foundation Framework中被广泛使用,举个简单的例子 NSArray *arr = [NSArray arrayWithObjects:@"foo",@"bar", nil]; NSLog(@"arr class:%@", [arr class]); // output:

iOS开发-类簇(Class Cluster)

类簇(Class  Cluster)是定义相同的接口并提供相同功能的一组类的集合,仅公开接口的抽象类也可以称之为类簇的公共类,每个具体类的接口有公共类的接口抽象化,并隐藏在簇的内部.这些类一般不能够直接使用,一般都是由公共类的子类来实现,可以称之为私有子类.看概念会觉得有点枯燥,其实最常用的NSString就是一个类簇,不过看起来不明显,比较明显的是NSNumber,numberWithInt,numberWithDouble,这些方法其实在调用NSNumber的时候父类实例化私有子类,返回对应

iOS之NSArray类簇简介-(copy、mutableCopy导致程序crash)

1.前言 开发时常常用数组对数据进行处理,对NSMutableArray进行操作时经常导致程序崩溃,特研究一下NSArray的类簇!涉及__NSPlaceholderArray.__NSArray0.__NSSingleObjectArrayI.__NSArrayI.__NSArrayM相关类. 2.分析NSArray 2.1.创建不可变出租 NSArray *placeholder = [NSArray alloc]; NSArray *arr1 = [placeholder init]; N

第9条:以“类簇模式”隐藏实现细节

类簇模式把实现细节隐藏在一套简单的公共接口(抽象基类)后面.以保持接口简洁,用户无须自己创建子类实例,只需调用基类方法创建即可. 例如:UIButton 的 buttonWithType: 工厂模式是创建类簇的办法之一. OC中的系统框架中普通使用此模式. 大部分collection类都是类簇. 判断实例所属的类型信息: isMemberOfClass:    是否在相同类中,不含子类. isKindOfClass:     判断某对象是否位于类簇(基类和子类)中.

OC中的类簇的使用和初始化方法中属性的使用

今天遇到了几个和字符串相关的内存问题,和大家分享一下 NSString *name = [[NSString alloc]initWithString:@"张三"];NSLog(@"%d",[name retainCount]); 这两行代码的打印结果是-1, NSString * aString = [[NSString alloc] initWithFormat:@"123"]; NSLog(@"%d",aString.r

机器学习-KMeans聚类 K值以及初始类簇中心点的选取

[转]http://www.cnblogs.com/kemaswill/archive/2013/01/26/2877434.html 本文主要基于Anand Rajaraman和Jeffrey David Ullman合著,王斌翻译的<大数据-互联网大规模数据挖掘与分布式处理>一书. KMeans算法是最常用的聚类算法,主要思想是:在给定K值和K个初始类簇中心点的情况下,把每个点(亦即数据记录)分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的

iOS类的合理设计,面向对象思想

每天更新的东西可能有反复的内容.当时每一部分的知识点是不同的,须要大家认真阅读 这里介绍了iOS类的合理设计.面向对象思想 main.m #import <Foundation/Foundation.h> #import "Iphone.h" int main(int argc, const char * argv[]) { Iphone * phone = [Iphone new]; phone->_color = IphoneColorWhite; phone-&

KMeans聚类 K值以及初始类簇中心点的选取 转

本文主要基于Anand Rajaraman和Jeffrey David Ullman合著,王斌翻译的<大数据-互联网大规模数据挖掘与分布式处理>一书. KMeans算法是最常用的聚类算法,主要思想是:在给定K值和K个初始类簇中心点的情况下,把每个点(亦即数据记录)分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的中心点(取平均值),然后再迭代的进行分配点和更新类簇中心点的步骤,直至类簇中心点的变化很小,或者达到指定的迭代次数. KMeans算法本