这篇博客讲解工厂模式
概念
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。
分类
工厂模式分类,简单工厂模式,工厂方法模式,抽象工厂模式
简单工厂模式
介绍
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
延伸
试想一下,当我们在codeing的时候,在A类里面只要NEW了一个B类的对象,那么A类就会从某种程度上依赖B类。如果在后期需求发生变化或者是维护的时候,需要修改B类的时候,我们就需要打开源代码修改所有与这个类有关的类了,做过重构的朋友都知道,这样的事情虽然无法完全避免,但确实是一件让人心碎的事情
场景
我发现大家写这类博客都喜欢弄个场景,那我也弄个吧。假设你非常喜欢唱歌,是个歌手,每天晚上你都会回家唱一首歌曲,今天你唱《天天喜欢你》,明天喜欢唱《十年》,后天唱《明天就要嫁给你》,你每天唱那一首歌都是随机的。
UML 图
简单工厂模式UML图
简单代码
#import <Foundation/Foundation.h>
@protocol Song -(void)sing;
@end
#import "Song.h"
@interface SongA :
NSObject
@end
#import "SongA.h"
@implementation SongA
-(void)sing{
NSLog(@"sing 《天天喜欢你》");
}
@end
#import "Song.h"
@interface SongB : NSObject
@end
#import "SongB.h"
@implementation SongB
-(void)sing{
NSLog(@"sing 《十年》");
}
@end
#import "Song.h"
@interface SongC : NSObject
@end
@implementation SongC
-(void)sing{
NSLog(@"sing 《明天就要嫁给你》");
}
@end
#import "SongA.h"
#import "SongB.h"
#import "SongC.h"
#import "Song.h"
typedef enum {
SongAType,
SongBType,
SongCType}SongType;
@interface SongFactory : NSObject
-(id)getSongType:(SongType)songType;
@end
#import "SongFactory.h"
@implementation SongFactory
-(id)getSongType:(SongType)songType{
if (songType==SongAType) {
return [SongA new];
}else if (songType==SongBType){
return [SongB new];
}else if (songType == SongCType){
return [SongC new];
}else{
return nil;
}
return nil;
}
@end
SongFactory * factory=[[SongFactory alloc]init]; id song = [factory getSongType:SongAType];
[song sing];
song = [factory getSongType:SongBType];
[song sing];
song = [factory getSongType:SongCType];
[song sing];
测试结果很简单
2018-04-02 17:31:55.153472+0800 创建型模式-工厂模式[31997:5155859] sing 《天天喜欢你》
2018-04-02 17:31:55.153638+0800 创建型模式-工厂模式[31997:5155859] sing 《十年》
2018-04-02 17:31:55.153745+0800 创建型模式-工厂模式[31997:5155859] sing 《明天就要嫁给你》
优点
简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
缺点
很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则
工厂方法模式
介绍
工厂方法模式Factory Method,又称多态性工厂模式。在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
定义
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。
延伸
在上面简单工厂的引入中,我们将实例化具体对象的工作全部交给了专门负责创建对象的工厂类(场务)中,这样就可以在你需要唱歌的时候后创建对应的歌曲(产品)类了。但是有时候唱歌有心情的,比如要唱一首新歌《青花瓷》,就必须要修改源码,增加一个if else。工厂方法就是解决这个问题而产生的。
模拟场景
假设你今天想场《青花瓷》,明天想唱《霸王别姬》,每天想增加一手新歌,因此工厂模式的扩展性增强很多
UML图
工厂方法模式UML图其实我们看这个图和简单工厂的UML图比较,就是将Factory 中根据type类型获取歌曲变成了每一个工厂生产特定的歌曲。这样每次增加一首歌曲,那么我们就增加一个factory就行了,不用在修改Factory类了
简单代码
歌曲abc 的代码没有任何变化
#import "Song.h"
@protocol MySongFactory<NSObject>
-(id)getSong;
@end
#import "MySongFactory.h"@interface SongFactoryA : NSObject<MySongFactory>
@end
#import "SongA.h"
@implementation SongFactoryA
-(id)getSong{
return [SongA new];
}
@end
#import "MySongFactory.h"
@interface SongFactoryB : NSObject<MySongFactory>
@end
#import "SongFactoryB.h"
#import "SongB.h"
@implementation SongFactoryB
-(id<Song>)getSong{
return [SongB new];
}
@end
#import "MySongFactory.h"
@interface SongFactoryC : NSObject<MySongFactory>
@end
#import "SongFactoryC.h"
#import "SongC.h"
@implementation SongFactoryC
-(id<Song>)getSong{
return [SongC new];
}
@end
测试代码
id<MySongFactory> factory=[SongFactoryA new];
id<Song> song = [factory getSong];
[song sing];
factory=[SongFactoryB new];
song = [factory getSong];
[song sing];
factory=[SongFactoryC new];
song = [factory getSong];
[song sing];
测试结果
2018-04-02 18:21:39.573105+0800 创建型模式-工厂模式[44856:5211772] sing 《天天喜欢你》
2018-04-02 18:21:39.573325+0800 创建型模式-工厂模式[44856:5211772] sing 《十年》
2018-04-02 18:21:39.573447+0800 创建型模式-工厂模式[44856:5211772] sing 《明天就要嫁给你》
优点
子类提供挂钩。基类为工厂方法提供缺省实现,子类可以重写新的实现,也可以继承父类的实现。-- 加一层间接性,增加了灵活性
屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,只需关心产品的接口,只要接口保持不变,系统中的上层模块就不会发生变化。
典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不需要关心,符合迪米特法则,符合依赖倒置原则,符合里氏替换原则。
多态性:客户代码可以做到与特定应用无关,适用于任何实体类。
缺点
需要Creator和相应的子类作为factory method的载体,如果应用模型确实需要creator和子类存在,则很好;否则的话,需要增加一个类层次。(不过说这个缺点好像有点吹毛求疵了)
源代码地址
借鉴博客
下一篇博客地址
网友评论