何为抽象工厂?设计模式
抽象工厂提供一个固定的接口,用于建立一系列有关联或相依存的对象,而没必要指定其具体类或其建立的细节。客户端与从工厂获得的具体对象之间没有耦合。框架
抽象工厂与工厂方法模式的区别spa
抽象工厂与工厂方法模式在许多方面有不少类似之处,以致于咱们经常搞不清楚应该在何时用哪个。两个模式都用于相同的目的:建立对象而不让客户端知晓返回了什么确切的具体对象。设计
抽象工厂:@、经过对象组合建立抽象产品。@、建立多系列产品。@、必须修改父类的接口才能支持新的产品。日志
工厂方法:@、经过类继承建立抽象产品。@、建立一种产品。@、子类化建立并重载工厂方法以建立新产品。code
在Cocoa Touch框架中使用抽象工厂对象
在Cocoa Touch框架中能够常常看到抽象工厂模式,不少基础类都采用了这一模式。好比NSNumber。建立NSNumber实例的方式彻底符合抽象工厂模式。继承
建立对象有两种方式,使用先alloc再init的方法,或者使用类中的+className...方法。NSNumber类有不少类方法用于建立各类类型的NSNumber对象,以下:接口
NSNumber *boolNumber = [NSNumber numberWithBool:YES]; NSNumber *intNumber = [NSNumber numberWithInt:10]; NSNumber *floatNumber = [NSNumber numberWithFloat:10.0]; NSNumber *doubleNumber = [NSNumber numberWithDouble:10.0];
每一个返回的对象属于表明最初输入值的不一样私有子类,能够用NSLog输出它们类的描述:ip
NSLog(@"%@", [[boolNumber class] description]); NSLog(@"%@", [[intNumber class] description]); NSLog(@"%@", [[floatNumber class] description]); NSLog(@"%@", [[doubleNumber class] description]);
将看到以下的日志信息:
2015-09-06 21:25:13.116 NSNumberDemo[59970:4475507] __NSCFBoolean 2015-09-06 21:25:13.117 NSNumberDemo[59970:4475507] __NSCFNumber 2015-09-06 21:25:13.117 NSNumberDemo[59970:4475507] __NSCFNumber 2015-09-06 21:25:13.117 NSNumberDemo[59970:4475507] __NSCFNumber
除了boolNumber的实际类型是NSCFBoolean之外,大多数实际类为NSCFNumber类型。尽管这些+className类工厂方法返回NSNumber具体子类的实例,可是返回的实例确实支持NSNumber的公有接口。
虽然它们属于NSNumber的不一样具体子类,可是其行为由抽象超类NSNumber定义,并且是公有的。以下代码所示:
NSLog(@"%d", [boolNumber intValue]); NSLog(@"%@", [floatNumber boolValue] ? @"YES" : @"NO");
将看到日志信息以下:
2015-09-06 21:32:59.234 NSNumberDemo[60043:4478868] 1 2015-09-06 21:32:59.234 NSNumberDemo[60043:4478868] YES
boolNumber在内部保持布尔值YES,但仍实现了公有intValue方法,返回其内部布尔值的适当整数值。floatNumber也是如此,它重载了boolValue方法,返回反映其内部浮点型值的适当布尔值。
接受不一样类型的参数并返回NSNumber实例的类方法是类工厂方法(工厂模式)。NSNumber的类工厂方法生产各类数工厂。numberWithBool:建立NSCFBoolean工厂的实例,而numberWithInt:建立NSCFNumber的实例。NSNumber中的类工厂方法定义了决定实例化何种私有具体子类(好比,NSCFBoolean或NSCFNumber)的默认行为。这一版本的工厂方法是传统工厂方法模式的一个变体,此处的抽象产品为做为工厂的具体NSNumber子类。NSNumber是抽象工厂实现的一个例子。基础框架中抽象工厂的此种特色被称为类簇。
类簇是基础框架中一种常见的设计模式,基于抽象工厂模式的思想。它将若干相关的私有具体工厂子类集合到一个公有的抽象超类之下。好比,数包含了各类数值类型的完整集合,如字符、浮点数、整数等。这些数值类型都是数的子集。因此NSNumber天然成为这些数子类型的超类型。NSNumber有一系列公有API,定义了各类类型的数所共有的行为。客户端在使用时无需知道NSNumber实例的具体类型。
类簇是抽象工厂的一种形式。好比,NSNumber自己是一个高度抽象的工厂,NSCFBoolean和NSCFNumber是具体工厂子类。子类是具体工厂,由于它们重载了NSNumber中声明的公有工厂方法以生产产品。例如,intValue和boolValue根据实际NSNumber对象的内部值返回一个值,虽然值的数据类型可能不一样。从这些工厂方法返回的实际值就是抽象工厂模式的最初定义中的所说产品。
建立抽象产品的工厂方法与建立抽象工厂的工厂方法之间有个不一样点。显然,像intValue和boolValue这样的工厂方法,应该在具体工厂(NSCFNumber与NSCFBoolean)中重载以返回产品。而像numberWithBool:和numberWithInt:这样的工厂方法并非为了返回产品,而是为了返回能返回产品的工厂,所以它们不该在具体子类重载。
总结
抽象工厂模式是一种极为常见的设计模式。它是最基本的,由于它能够涉及许多类型的对象建立。一系列相关的类,应该做为一种抽象,不为客户端所见。抽象工厂则能够方便的解决这个问题,而不暴露建立过程当中任何没必要要的细节或所建立对象的确切类型。