何为工厂方法模式?
工厂方法也称为虚构造器,它适用于这种情况:一个类无法预期需要生成哪个类的对象,想让其子类来指定所生成的对象。
工厂方法模式:定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到其子类。
何时使用工厂方法
@:编译时无法准确预期要创建的对象的类。
@:类想让子类决定运行时创建什么。
@:类有若干辅助类为其子类,而你想要将返回哪个子类这一信息局部化。
使用这一模式的最低限度是,工厂方法能给予类在变更返回哪一种对象这一点上更多的灵活性。
与直接创建新的具体对象相比,使用工厂方法创建对象可算作一种最佳做法。工厂方法模式让客户程序可以要求由工厂方法创建的对象拥有一组共同的行为。所以往类层次结构中引入新的具体产品并不需要修改客户端代码。因为返回的任何具体对象的接口都跟客户端一直在用的接口相同。
在Cocoa Touch框架中应用工厂方法
比如NSNumber有很多numberWith*方法;其中有两个是numberWithBool:和numberWithChar:。它们是类方法,也就是说我们向NSNumber发送[NSNumber numberWithBool:bool]与[NSNumber numberWithChar:char],以获得与传入参数同类型的各种NSNumber实例。与如何创建NSNumber的具体子类的实例有关的所有细节,都由NSNumber的类工厂方法负责。[NSNumber numberWithBool:bool]的情况是,方法接受值bool,并把NSNumber的内部子类的一个实例初始化,让它能够反映传入的值bool。
工厂方法的应用
我们通过一个协议让工厂对象具有相同的方法,在协议里面我们声明一个计算的方法,用来做两个数的计算,代码如下:
#import <Foundation/Foundation.h> @protocol Calculate <NSObject> @property (nonatomic, assign) float numberA; @property (nonatomic, assign) float numberB; - (float)calculate; @end
然后我们定义两个类来具体的计算,分别是求和计算与相乘计算,代码如下:
#import <Foundation/Foundation.h> #import "Calculate.h" @interface AddCalculate : NSObject <Calculate> - (float)calculate; //重写该方法 @end
#import "AddCalculate.h" @implementation AddCalculate @synthesize numberA = _numberA; @synthesize numberB = _numberB; - (float)calculate { return self.numberA + self.numberB; } @end
#import <Foundation/Foundation.h> #import "Calculate.h" @interface MultiplyCalculate : NSObject <Calculate> - (float)calculate; @end
#import "MultiplyCalculate.h" @implementation MultiplyCalculate @synthesize numberA = _numberA; @synthesize numberB = _numberB; - (float)calculate { return self.numberA*self.numberB; } @end
这样具体的计算已经由这两个类来进行实现了,下面我们来创建相应的工厂方法,首先我们创建一个抽象的工厂类,Factory代码如下:
#import <Foundation/Foundation.h> #import "Calculate.h" @interface Factory : NSObject <Calculate> - (id)createFactory; @end
#import "Factory.h" @implementation Factory @synthesize numberA = _numberA; @synthesize numberB = _numberB; - (id)createFactory { NSLog(@"具体返回什么对象,由子类来决定"); return nil; } - (float)calculate { return -1; //默认返回-1 } @end
从代码中我们可以看到,抽象的Factory定义了工厂方法创建的对象的接口。但具体返回什么对象要由其子类来进行确定,AddFactory类的代码如下:
#import "Factory.h" @interface AddFactory : Factory - (id)createFactory; //重写该方法 @end
#import "AddFactory.h" #import "AddCalculate.h" @implementation AddFactory - (id)createFactory { return [[AddCalculate alloc] init]; } @end
MultiplyFactory代码如下:
#import "Factory.h" @interface MultiplyFactory : Factory - (id)createFactory; @end
#import "MultiplyFactory.h" #import "MultiplyCalculate.h" @implementation MultiplyFactory - (id)createFactory { return [[MultiplyCalculate alloc] init]; } @end
从代码中我们可以看到,AddFactory与MultiplyFactory实现了createFactory接口,定义了返回对象的工厂方法。下面我们看下在客户端怎么使用工厂模式,客户端代码如下:
#import "ViewController.h" #import "Calculate.h" #import "AddCalculate.h" #import "MultiplyCalculate.h" #import "Factory.h" #import "AddFactory.h" #import "MultiplyFactory.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Factory *factory = [[AddFactory alloc] init]; Factory *calculate = [factory createFactory]; calculate.numberA = 10.0; calculate.numberB = 20.0; float sum = [calculate calculate]; NSLog(@"sum is = %f", sum); Factory *factory1 = [[MultiplyFactory alloc] init]; Factory *calculate1 = [factory1 createFactory]; calculate1.numberA = 10.0; calculate1.numberB = 20.0; float multiply = [calculate1 calculate]; NSLog(@"sum is = %f", multiply); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
输出端如下:
2015-09-04 22:51:06.298 FactoryPattern[49484:2688173] sum is = 30.000000 2015-09-04 22:51:06.299 FactoryPattern[49484:2688173] multiply is = 200.000000
从这个例子我们可以看出,工厂方法从代码中消除了对应用程序特有类的耦合。代码只需要处理Factory抽象接口,所以同一代码得以复用,在应用程序中与用户定义的任何具体类一起工作。
demo链接地址:https://github.com/guoshimeihua/FactoryPattern.git