常用工厂模式有简单工厂模式、工厂方法模式、抽象工厂模式
什么是简单工厂模式?
简单工厂模式中定义一个抽象类,抽象类中声明公共的特征及属性,抽象子类继承自抽象类,去实现具体的操作。工厂类根据外界需求,在工厂类中创建对应的抽象子类实例并传给外界,而对象的创建是由外界决定的。外界只需要知道抽象子类对应的参数即可,而不需要知道抽象子类的创建过程,在外界使用时甚至不用引入抽象子类。
简单工厂模式将操作对象的创建,和关于操作对象相关的业务逻辑分离开,降低操作对象的耦合度。由于工厂类只是为外界创建对象,所以并不需要实例化工厂类对象,只需要为外界提供类方法即可。外界需要什么类型的抽象子类,只需要传递对应的参数即可。
简单工厂模式主要包含三部分:
- 工厂类:根据外界的需求,决定创建并返回哪个具体的抽象子类。
- 抽象类:定义抽象子类所需的属性和方法,子类通过继承自抽象类获得这些方法。
- 抽象子类:继承自抽象类,是具体操作的实现者。
业务场景
简单工厂模式主要适用于抽象子类的业务逻辑相同,但具体实现不同的情况。不同的操作子类执行同样的方法,最后的结果却是不同的,这也是多态的一种表现方式。
这里用一个简单的加减乘除的基础运算例子来说明一下,下面的UML类图和代码都会依据这个场景来实现。假设现在需要实现一个简单的加减乘除运算,这些运算具体操作都是类似的,都有两个被操作的值,只是运算符不同,这种情况就适合用简单工厂模式。
UML类图

从上面图中我们可以看出,图中定义了一个运算抽象类,所有的运算操作类继承自这个运算抽象类。运算抽象类有两个参与运算的属性,通过调用getResult方法来获取这两个值最后运算的结果,调用方式都一样,只是最后的结果不同。抽象类并不参与运算,运算的结果通过运算操作类重载getResult方法去实现。
上图中还定义了一个简单工厂类,这个简单工厂类就是用于实现运算操作类实例化的逻辑,通过外界传进来的type参数,并将实例完成的运算操作类返回。
代码实现
首先定义抽象类,抽象类中将会包含参与运算的抽象子类的属性和行为(方法)。
Operation(抽象运算类)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, OperationType) { OperationTypeAdd, OperationTypeSub, OperationTypeMul, OperationTypeDiv };
@interface Operation : NSObject
@property (nonatomic, assign) CGFloat numberA;
@property (nonatomic, assign) CGFloat numberB;
- (CGFloat)getResult;
@end
|
1 2 3 4 5 6 7 8
| #import "Operation.h"
@implementation Operation - (CGFloat)getResult { NSAssert(NO, @"%s must be overridden by subclasses", __func__); return 0; } @end
|
定义抽象类之后,需要创建负责具体运算的抽象子类,也就是操作类,简单的定义了一下,以加法类为例,代码太多就不全贴出来了。
OperationAdd(加法类)1 2 3 4 5
| #import "Operation.h"
@interface OperationAdd : Operation
@end
|
1 2 3 4 5 6 7
| #import "OperationAdd.h"
@implementation OperationAdd -(CGFloat)getResult { return self.numberA + self.numberB; } @end
|
现在具体参与运算的类都已经定义完成,就需要定义工厂类了。工厂类的职责就是根据外界需要,创建对应的抽象子类实例并返回给外界。
OperationFactory(简单的工厂类)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #import <Foundation/Foundation.h> #import "Operation.h"
@interface OperationFactory : NSObject
简单的工厂方法用于创建运算实例
@param operationType 运算类型 @return 运算实例 */ + (Operation *)createOperation:(OperationType) operationType;
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #import "OperationFactory.h" #import "OperationAdd.h" #import "OperationSub.h" #import "OperationMul.h" #import "OperationDiv.h"
@implementation OperationFactory
+ (Operation *)createOperation:(OperationType) operationType { switch (operationType) { case OperationTypeAdd: { return [[OperationAdd alloc] init]; } break; case OperationTypeSub: { return [[OperationSub alloc] init]; } break; case OperationTypeMul: { return [[OperationMul alloc] init]; } break; case OperationTypeDiv: { return [[OperationDiv alloc] init]; } break; default: return nil; break; } }
@end
|
上面我们就将工厂设计模式的定义都完成了,现在需要的就是外界直接拿来使用了。上面工厂类直接定义的类方法,因为外界获取某个具体的抽象子类时,并没有必要将工厂类实例化,工厂类只是完成一个功能。
SimpleFactoryTests1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| - (void)testSimpleFactory { Operation *operation = [OperationFactory createOperation:OperationTypeAdd]; operation.numberA = 100; operation.numberB = 25; XCTAssertTrue([operation getResult] == 125); operation = [OperationFactory createOperation:OperationTypeSub]; operation.numberA = 100; operation.numberB = 75; XCTAssertTrue([operation getResult] == 25); operation = [OperationFactory createOperation:OperationTypeMul]; operation.numberA = 100; operation.numberB = 25; XCTAssertTrue([operation getResult] == 2500); operation = [OperationFactory createOperation:OperationTypeDiv]; operation.numberA = 100; operation.numberB = 25; XCTAssertTrue([operation getResult] == 4); }
|
到目前为止简单工厂模式的代码就写完了,可以看到外界想进行什么类型的运算,只需要将传入的运算类型参数改一下即可,工厂类就会实例化其他的抽象子类进行运算。但是这种工厂类的设计,有一个很大的问题,就在于每次增加或删除某个算法时,都需要对工厂类进行修改,这是不符合开放封闭原则的。对于这个问题,我们以后将会通过反射机制来进行处理,这里就不做说明了。