在我们编程的世界里面,有所谓很高深的23种设计模式,而且将其中常见的设计模式分为三类:创建型模式、行为型模式、结构型模式。
IOS的系统类库中也有一种方式使得我们不需要关注类中的具体的实现,但可以根据不同需求场景创建出合适的对象来。比如Foundation中的NSArray,UIkit中的UIButton。
三种工厂模式
常见的有Factory Method和Abstract Factory,还有一个Simple Factory。
今天就来说说Simple Factory,产品有一个统一interface,可以有不同的implementation,同时有一个工厂对象。需要产品的时候,工厂会根据已有条件做选择,选择一种产品实现,构建一个实例出来。这种设计将产品的抽象和实现分离开来,可以针对统一的产品进行接口进行通信,而不必特意关注具体现在的不同。对于产品类别的扩充也是可以的,但每增加一个产品,都需要修改工厂的逻辑,有一定维护成本。
工厂方法更进一步,将工厂也抽象出来,进行接口、实现分级。这样具体工厂和具体产品可以对应着同时扩充,而不需要修改现有逻辑。当然,使用者也许在不同场景要在一定程度上自己对应的工厂选择。
抽象工厂相对于工厂方法主要是对整个产品类的体系进行了横向扩充,构成一个更为完整的系统。
OC的类族
我们每天用到的NSNumber的numberWith...方法。但大家有可能都不知道NSNumber这样的方法调用返回的不是NSNumber类本身的对象。
Number的概念很大,隐藏了很多子类,我们通过nsnumber的numberWith方法得到的对象正是他的子类对象,我们却不需要知道这些,只要知道它是一个NSNumber对象就好了。
Simple Concept and Simple Interface,这是apple设计类族的初衷,也是优点所在。可以想象我们要用整数作为参数拿到一个NSNumber对象和一个布尔值参数拿到的NSNumber对象是不同的,这略微有些类似于switch逻辑,根据不同的条件提供不同的子类对象,而这一切都集中声明在公共接口类NSNumber中,仿佛和上面的simple factory一样的。当然缺点就是不是很好扩展。
类族的子类扩展
了解了类族的概念,我们在实际开发中也可以采用其方法,利用其有点。虽然其子类扩展很难,但是不代表就没法继承了,我们可以去定义子类的。
要做子类,有几个条件必须满足,首先要以公共“抽象”类为父类,比如NSNumber,NSArray;其次要提供自定义存储,然后要覆盖父类初始化方法,最后重写父类的“原始”方法
其中自定义存储很重要,系统的类族一般都是提供了各种方法声明,然而自身却不提供存储,所以子类一定要提供自己的存储,这也是自定义子类的意义。
而重写“原始”方法,这个要说一下。按照苹果的文档,和指定初始化方法形式类似,这些类里面的众多方法可以分为两类,“原始”方法和“衍生”方法。“原始”方法定义了这个类及对象的最基本行为,而“衍生”方法则基于这些“原始”方法进行更复杂逻辑的包装。所以,重写了“原始”方法,“衍生”方法也自然效果就不同了。
另外还建议对类族类进行包装。
对象所属类的判断
或许我们会想,那些系统写的好的,够用了,我去考虑这个干什么,那么了解类族的意义在哪呢?意义当然有的,举个例子:
[NSNumber numberWithInt:2]
[NSNumber numberWithBool:YES]
都是NSNumber,一个是_NSCFNumber,另一个是_NSCFBoolean。
那么我们直接判断的话就会出问题比如
id maybeAnArray = /* ... */;
if ([maybeAnArray class] == [NSArray class]) {
// Will never be hit
}
这个时候就需要 isMemberOfClass 或者是 isKindOfClass。
这只是浅显的讲述一下,具体可以看看 APPLE 的官方文档 ClassClusters。
下期讲讲令人上瘾的ARC!