标签:
何为抽象工厂?
抽象工厂提供一个固定的接口,用于创建一系列有关联或相依存的对象,而不必指定其具体类或其创建的细节。客户端与从工厂得到的具体对象之间没有耦合。
抽象工厂与工厂方法模式的区别
抽象工厂与工厂方法模式在许多方面有很多相似之处,以至于我们常常搞不清楚应该在什么时候用哪一个。两个模式都用于相同的目的:创建对象而不让客户端知晓返回了什么确切的具体对象。
抽象工厂:@、通过对象组合创建抽象产品。@、创建多系列产品。@、必须修改父类的接口才能支持新的产品。
工厂方法:@、通过类继承创建抽象产品。@、创建一种产品。@、子类化创建并重载工厂方法以创建新产品。
在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输出它们类的描述:
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:这样的工厂方法并不是为了返回产品,而是为了返回能返回产品的工厂,因此它们不应在具体子类重载。
总结
抽象工厂模式是一种极为常见的设计模式。它是最基本的,因为它可以涉及许多类型的对象创建。一系列相关的类,应该作为一种抽象,不为客户端所见。抽象工厂则可以方便的解决这个问题,而不暴露创建过程中任何不必要的细节或所创建对象的确切类型。
标签:
原文地址:http://my.oschina.net/daguoshi/blog/501928