前言
- 最近重阅设计模式相关的书籍,阅读时无不感慨前人的智慧,希望以此文为头,记下与设计模式相关的笔记
目录
- 简单工厂模式的介绍
- 基础理论
- 深入理解
- UML图
- 优与劣
- 简单工厂模式的使用实例
- 简单工厂模式在系统框架中的应用
正文
简单工厂模式介绍
- 基础理论
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现
—— 百度百科
- 深入理解
- 所谓简单工厂模式,本质就是根据传入的参数进行判断,动态选择不同的子类进行初始化。而为了方便对外使用,我们只暴露一个最最简单易用的父类 / 接口 / 工厂类。
- 根据上述定义,我认为简单工厂模式有以下两种:
- 形式I:抽象父类 + 具体子类(静态工厂方法定义在抽象父类中,该形式又被称作类簇模式,见UML图上半部分)
- 形式II:工厂类 + 抽象父类 / 接口 + 具体子类(静态工厂方法定义在工厂类中,见UML图下半部分)
- UML图
- 优与劣
- 优:隐藏了实现类,用户在使用的时候无需知道对象如何构建的,对外仅暴露了必要的接口。
- 劣:扩展时违反开闭原则(OCP,Open Closed Principle),当新增加子类的时候,需要修改在抽象父类 / 工厂类中的静态工厂方法。
简单工厂模式的使用实例
下面以一个简单的二元加减乘除计算器为例,讲述简单工厂模式的应用
创建父类:在本例中,父类为基础二元算术运算类
12345678910111213141516171819202122// Operation.htypedef NS_ENUM(NSUInteger, OperationType) {OperationTypeAdd,OperationTypeSub,OperationTypeMul,OperationTypeDiv,OperationTypeDefault};typedef NSInteger OperandType;@interface Operation : NSObject+ (instancetype)operationWithType:(OperationType)type;- (OperandType)calculate;@property (nonatomic, assign, readwrite) OperandType operandA;@property (nonatomic, assign, readwrite) OperandType operandB;@end简单实现父类:本例采用形式I的简单工厂模式,故工厂方法放在父类中
123456789101112131415161718192021222324252627// Operation.m@implementation Operation+ (instancetype)operationWithType:(OperationType)type {switch (type) {case OperationTypeAdd:return [[OperationAdd alloc] init];case OperationTypeSub:return [[OperationSub alloc] init];case OperationTypeMul:return [[OperationMul alloc] init];case OperationTypeDiv:return [[OperationDiv alloc] init];case OperationTypeDefault:return [[[self class] alloc] init];}}- (OperandType)calculate {// virtual implementNSAssert(NO, @"virtual implement shouldn`t be called by");return -1;}@end创建继承于父类的子类:本例中,子类为具体的操作类,负责实现操作运算。此处子类重写父类方法,以便合理使用多态
12345678910111213141516171819// OperationAdd.h@interface OperationAdd : Operation- (OperandType)calculate;@end// OperationAdd.m@implementation OperationAdd- (OperandType)calculate {return super.operandA + super.operandB;}@end12345678910111213141516171819// OperationSub.h@interface OperationSub : Operation- (OperandType)calculate;@end// OperationSub.m@implementation OperationSub- (OperandType)calculate {return super.operandA - super.operandB;}@end12345678910111213141516171819// OperationMul.h@interface OperationMul : Operation- (OperandType)calculate;@end// OperationSub.m@implementation OperationSub- (OperandType)calculate {return super.operandA - super.operandB;}@end1234567891011121314151617181920212223// OperationDiv.h@interface OperationDiv : Operation- (OperandType)calculate;@end// OperationDiv.m@implementation OperationDiv- (OperandType)calculate {if (super.operandB != 0) {return super.operandA / super.operandB;} else {return NSIntegerMax;}}@end实现简单工厂方法:实现父类中的简单工厂方法,根据类型判断返回的实例
1234567891011121314151617181920// Operation.m+ (instancetype)operationWithType:(OperationType)type {switch (type) {case OperationTypeAdd:return [[OperationAdd alloc] init];case OperationTypeSub:return [[OperationSub alloc] init];case OperationTypeMul:return [[OperationMul alloc] init];case OperationTypeDiv:return [[OperationDiv alloc] init];case OperationTypeDefault:return [[[self class] alloc] init];}}至此,简单工厂模式实现完毕
简单工厂模式在系统框架中的应用
NSString
我们查阅
NSString
API文档时会发现,有下面这一段话The objects you create using
NSString
andNSMutableString
are referred to as string objects (or, when no confusion will result, merely as strings). The term C string refers to the standardchar *
type. Because of the nature of class clusters, string objects aren’t actual instances of theNSString
orNSMutableString
classes but of one of their private subclasses. Although a string object’s class is private, its interface is public, as declared by these abstract superclasses,NSString
andNSMutableString
. The string classes adopt theNSCopying
andNSMutableCopying
protocols, making it convenient to convert a string of one type to the other.NSString
类是一个类簇类。所谓类簇类,实际上是一个隐含着许多私有类的类。一般类簇类都带有工厂方法。我们查看NSString
头文件,可以发现许多工厂方法(见下)。其本质亦是简单工厂模式,类簇类的私有类放在父类.m
文件中。然后其利用传入的参数作为判断标准,生成私有类的实例,并作为NSString
实例返回。123456+ (instancetype)string;+ (instancetype)stringWithString:(NSString *)string;+ (instancetype)stringWithCharacters:(const unichar *)characters length:(NSUInteger)length;+ (nullable instancetype)stringWithUTF8String:(const char *)nullTerminatedCString;+ (instancetype)stringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);+ (instancetype)localizedStringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);实际上,在系统框架中许多类都是以类簇的方式实现的,而以这种方式实现的类一般又含有类簇形式的简单工厂方法,因此类簇模式与简单工厂模式可谓是相得益彰。
- 总结:本文简述了简单工厂模式的理论以及实践。我认为,简单工厂模式本质是根据传入的参数进行判断,动态选择不同的子类进行初始化。只要把握好这一本质,便能理清简单工厂模式。
- 本文代码下载
- 示例代码
- 运行环境:Xcode 8.2.1 (8C1002)
- 推荐阅读
- Last Edited:2017.2.17
- Author:@Seahub
- Please contact me if you want to share this Article, 3Q~