iOS 工厂模式
前言
笔者之前学习了有关于设计模式的六大原则,之前简单了解过这个工厂模式,今天主要是重新学习一下这个模式,正式系统性的学习一下这个模式
工厂模式
工厂模式就是指我们在创建对象的时候不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象,在OC中最经典的例子是下面这个:
UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem];
这里我们并不处理创建逻辑,而是通过我们需要什么就会创建出对应需求的一个button
工厂模式主要分成三类:
- 简单工厂: 简单工厂不是一个模式,而是一种编程习惯,提供一个创建对象实例的功能,而无需关系他的具体实现.被创建的类型可以是接口,抽象类,具体类
- 工厂模式:要依赖抽象,不要依赖具体
- 抽象工厂模式:提供一个创建一系列相关或者互相依赖的接口,而无需依赖具体类
简单工厂
简单工厂模式(Simple Factory Pattern):专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常都具有共同的父类。
就相当于一个工厂添加新的产品.
总结来说,就是将各式各样if-else的判断由业务层,放到了工厂类里面
简单工厂模式的结果比较简单:
- 工厂:工厂负责创建所有产品实例的逻辑
- 具体产品:工厂锁创建的所有产品对象类,它以自己的方式来实现其共同父类声明的接口
案例
一个商店中售卖不同品牌的手机:华为手机,小米手机,苹果手机
场景分析
- 工厂:Phone, 手机工厂类
- 具体产品:华为手机,小米手机,苹果手机
- (Factory *)sellPhone:(NSString *)type {
if ([type isEqualToString:@"ApplePhone"]) {
ApplePhone* phone = [[ApplePhone alloc] init];
return phone;
} else if ([type isEqualToString:@"HuaWeiPhone"]) {
HuaWeiPhone* phone = [[HuaWeiPhone alloc] init];
return phone;
} else if ([type isEqualToString:@"RedmiPhone"]) {
RedmiPhone* phone = [[RedmiPhone alloc] init];
return phone;
}
return nil;
}
苹果类
- (void)sellPhone{
NSLog(@"售卖苹果手机");
}
其他类也类似
我们可以把具体创建的信息放在某一个产品自己类中.这样把它封装好,然后我们客户端调用的时候就可以直接调用最外层的工厂方法:
- (Factory *)sellPhone:(NSString *)type // 外层只用调用这个方法就可以获得对应的实例
这样我们就可以把创建处理的内容放在对应的类中去,可以减少对于外部工厂的修改,让逻辑更紧密,逻辑封装的更好
优点
客户端只需要给工厂类传入一个正确的(约定好的)参数,就可以获取你所需要的对象,而不需要知道其创建细节,一定程度上减少系统的耦合
缺点
如果我们要是在添加Cell
,那么我们就需要修改FactoryCell
的方法,违反了开闭原则。
简单来说就是违反了依赖倒置原则,让高层组件client依赖于底层组件。违反这个原则的后果就是一旦底层组件改动,那么高层组件也就必须改动,违反了开闭原则。
小结
什么时候使用简单工厂
- 想完全封装隔离具体实现,让外部只能通过抽象类或者接口来操作,在上面的例子中,就是只操作
factory
,而不操作具体类,此时可以使用简单工厂,让客户端通过简单工厂来选择创建具体的类,不需要创建的具体过程 - 想把创建对象的职责集中管理,一个简单啊工厂可以创建许多相关或者不相关的对象,所以可以把对象的创建集中到简单工厂中进行管理
工厂模式
工厂方法模式(Factory Method Pattern)又称为工厂模式,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过不同的工厂子类来创建不同的产品对象。
不同的工厂生成不同的子类.通过协议来实现一个继承的效果,这样可以统一调用协议方法,然后不同的工厂重写协议函数实现对应的一个产品的创建
这里的适用场景其实与简单工厂类似,都是创建数据行为都比较类似的对象,但是和简单工厂不同的是,在工厂方法模式中,因为常化钢建对象的责任交给了抽象工厂的子类,因此客户端需要知道其所需的产品对应的工厂子类,而不是简单工厂中的参数
工厂模式主要包括:
- 抽象工厂:抽象工厂负责声明具体工厂的创建产品的接口
- 具体工厂:具体工厂负责创建产品
- 具体产品:具体产品是工厂所创建的所有产品对象类,它用自己的方式来实现共同父类声明的接口
这对卖手机的案例我们新的UML图
通过工厂模式定义我们知道,工厂模式主要是把对象的创建延迟到子类执行
创建工厂的一个抽象类
@protocol PhoneMakeProtocol <NSObject>
+ (id<PhoneProtocol>)sellPhone:(NSInteger)type; // <PhoneProtocol> 这个协议是意味着这个类可以被认为是我们的手机类
@end
然后让工厂实例:
// 苹果手机的工厂类
@interface iPhoneFactory : NSObject <PhoneProtocol>
@end
@implementation iPhoneFactory
- (id<PhoneProtocol>)sellPhone:(NSInteger)type {
return [[ApplePhone alloc] init];
}
@end
产品的抽象类:
@interface ApplePhone : NSObject <PhoneProtocol>
- (void)sellPhone;
@end
@implementation ApplePhone
- (void)sellPhone{
NSLog(@"售卖苹果手机");
}
@end
这样客户端就可以根据我们不同的工厂获取不同的一个iPhone的内容
客户端调用
factory = [iPhoneFactory new];
ApplePhone* phone = = [factory sellPhone:11];
[phone sellphone];
优点
更容易扩展新版本,如果需要加入新的实现,只需要扩展一个新类,然后继承抽象接口实现工厂方法即可。遵循了开闭原则
缺点
具体产品和工厂方法耦合,因为在工厂方法中需要创建具体实例,所以它们会耦合
抽象工厂模式
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。比如系统中有多于一个的产品族,而每次只使用其中某一产品族,属于同一个产品族的产品将在一起使用
接着看新的业务:
仔细看一下这六个产品的特点,我们可以把这它们划分在三个产品族里面:
- 1、苹果产品族:苹果手机,苹果电脑
- 2、小米产品族:小米手机,小米电脑
- 3、华为产品族:华为手机,华为电脑
这样我们只需要添加艾一个新的方法就变成了一个抽象工厂
三个模式对比
- 当单一类型产品比较少的时候,用简单工厂模式
- 单一产品各种定制比较多的时候,用工厂模式
- 多种类型产品的时候,使用抽象工厂模式
- 抽象工厂模式和工厂模式 工厂模式针对单独产品的创建,而抽象工厂注重一个产品系列的创建。如果产品系列只有一个产品的 话,那么抽象工厂就退换到工厂模式了。在抽象工厂中使用工厂方法来提供具体实现,这个时候他们联 合使用。
- 工厂模式和简单工厂 两者非常类似,都是用来做选择实现的。不同的地方在于简单工厂在自身就做了选择实现。而工厂模式 则是把实现延迟到子类执行。如果把工厂方法的选择实现直接在父类实现,那么此时就退化为简单工厂 模式了。
- 简单工厂和抽象工厂 简单工厂用于做选择实现,每个产品的实现之间没有依赖关系。而抽象工厂实现的一个产品系列,相互 之间有关联。这是他们的区别