工厂模式可以简单概括为同类型不同型号的产品有各自对应的工厂进行生产。
比如iPhone手机旗下有iPhoneX及iPhone8两种型号的手机,iPhoneX有自己iPhoneX的专属工厂进行生产,而iPhone8有自己iPhone8的专属工厂进行生产。两条生产线没有交集互不影响,后期如果新增或废弃相关类型的产品也不会影响到原有的生产线。
三种模式
简单工厂模式:简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
工厂模式:抽象了工厂接口的具体产品,应用程序的调用不同工厂创建不同产品对象。(抽象产品)
抽象工厂模式:在工厂模式的基础上抽象了工厂,应用程序调用抽象的工厂发发创建不同产品对象。(抽象产品+抽象工厂)
一、简单工厂模式
1、简单工厂模式定义
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
注意:简单工厂模式并不属于GoF 23个经典设计模式,但通常将它作为学习其他工厂模式的基础。
简单工厂模式的要点:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
2、简单工厂模式包含的角色
Factory(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法factoryMethod(),它的返回类型为抽象产品类型Product。
Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。
ConcreteProduct(具体产品角色):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。
简单工厂模式的要点:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
3、结构图
父类Fruits具有一个属性name和一个方法sweet、poorTaste,AppleFruit和OrangeFruit继承自Fruits,简单工厂类为FruitFactory,负责根据传入的不同参数FruitType来决定生产的是AppleFruit还是OrangeFruit。
4、示例
本Demo还是以小贩卖苹果和橘子为例:(小贩就是一个工厂,他为你提供苹果,橘子等水果)
- 先创建Fruits水果类,有一个sweet()、poorTaste()抽象方法,表示抽象产品类;
- 然后创建AppleFruit和OrangeFruit类,继承自Fruits类,表示具体产品类;
- 然后创建FruitFactory工厂类,有一个fruitsFactory:type方法,声明但未实现,表示抽象工厂;
具体代码如下:
Fruits类:
#import <Foundation/Foundation.h> //Fruits.h
@interface Fruits : NSObject
/**水果名*/
@property (nonatomic,copy) NSString *name;
- (void)sweet; /**< 甜 */
- (void)poorTaste; /**< 不好吃 */
@end
#import "Fruits.h" //Fruits.m
@implementation Fruits
// 甜
- (void)sweet {}
// 不好吃
- (void)poorTaste {}
@end
AppleFruit和OrangeFruit类
/*------------------AppleFruit------------------*/
#import "Fruits.h" //AppleFruit.h
//遵循了开闭原则
@interface AppleFruit : Fruits
- (void)freshApple; /**< 新鲜的苹果 */ // 开闭原则
@end
#import "AppleFruit.h" //AppleFruit.m
@implementation AppleFruit
@synthesize name;
// 甜
- (void)sweet {
NSLog(@"%@非常甜的啦-----%s",self.name, __func__);
}
// 不好吃
- (void)poorTaste {
NSLog(@"%@不好吃的啦-----%s",self.name,__func__);
}
// 新鲜的苹果
- (void)freshApple {
NSLog(@"%@是新鲜的-----%s",self.name,__func__);
}
@end
/*------------------OrangeFruit------------------*/
#import "Fruits.h" //OrangeFruit.h
@interface OrangeFruit : Fruits
- (void)acidOrange; /**< 酸橘子 */
@end
#import "OrangeFruit.h" //OrangeFruit.m
@implementation OrangeFruit
@synthesize name;
// 甜
- (void)sweet {
NSLog(@"%@非常甜的啦-----%s",self.name, __func__);
}
// 不好吃
- (void)poorTaste {
NSLog(@"%@不好的啦-----%s",self.name, __func__);
}
/**< 酸橘子 */
- (void)acidOrange {
NSLog(@"%@有点酸-----%s",self.name, __func__);
}
@end
FruitFactory类:
#import <Foundation/Foundation.h> //FruitFactory.h
#import "Fruits.h"
#import "AppleFruit.h"
#import "OrangeFruit.h"
typedef NS_ENUM(NSInteger,FruitType){
FruitTypeApple,
FruitTypeOrange,
};
@interface FruitFactory : NSObject
// 创造水果的工厂
+ (Fruits *)fruitsFactory:(FruitType)type;
@end
#import "FruitFactory.h" //FruitFactory.m
@implementation FruitFactory
+ (Fruits *)fruitsFactory:(FruitType)type {
// 创建空的对象.在工厂方法里面进行水果的制造
Fruits *fruits = nil;
switch (type) {
case FruitTypeApple:
fruits = [[AppleFruit alloc] init];
break;
case FruitTypeOrange:
fruits = [[OrangeFruit alloc] init];
break;
default:
break;
}
return fruits;
}
@end
运行代码:
#import "ViewController.h"
#import "FruitFactory.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/*###############SimpleFactoryPattern(简单工厂模式)######################*/
// 在水果工厂里面创建出苹果
Fruits *fruit = [FruitFactory fruitsFactory:FruitTypeApple];
fruit.name = @"苹果";
[fruit sweet];
// 在水果工厂里面创建出苹果
Fruits *fruit1 = [FruitFactory fruitsFactory:FruitTypeOrange];
fruit1.name = @"橘子";
[fruit1 poorTaste];
// 在水果工厂里面创建出苹果, 调用私有的方法
AppleFruit *apple = (AppleFruit*)[FruitFactory fruitsFactory:FruitTypeApple];
apple.name = @"苹果";
[apple freshApple];
// 在水果工厂里面创建出橘子, 调用私有的方法
OrangeFruit *orage = (OrangeFruit *)[FruitFactory fruitsFactory:FruitTypeOrange];
orage.name = @"橘子";
[orage acidOrange];
}
@end
打印结果:
2019-12-10 16:07:55.643264+0800 设计模式[78854:2676436] 苹果非常甜的啦------[AppleFruit sweet]
2019-12-10 16:07:55.643415+0800 设计模式[78854:2676436] 橘子不好的啦------[OrangeFruit poorTaste]
2019-12-10 16:07:55.643524+0800 设计模式[78854:2676436] 苹果是新鲜的------[AppleFruit freshApple]
2019-12-10 16:07:55.643629+0800 设计模式[78854:2676436] 橘子有点酸------[OrangeFruit acidOrange]
5、总结
简单工厂模式的简化:有时候,为了简化简单工厂模式,我们可以将抽象产品类和工厂类合并,将静态工厂方法移至抽象产品类中。比如在Fruits类中添加一个方法:
Fruits类:
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger,FruitType){
FruitTypeApple,
FruitTypeOrange,
};
@interface Fruits : NSObject
/**水果名*/
@property (nonatomic,copy) NSString *name;
- (void)sweet; /**< 甜 */
- (void)poorTaste; /**< 不好吃 */
// 创造水果的工厂
+ (Fruits *)fruitsFactory:(FruitType)type;
@end
#import "Fruits.h"
#import "AppleFruit.h"
#import "OrangeFruit.h"
@implementation Fruits
// 甜
- (void)sweet {}
// 不好吃
- (void)poorTaste {}
+ (Fruits *)fruitsFactory:(FruitType)type {
// 创建空的对象.在工厂方法里面进行水果的制造
Fruits *fruits = nil;
switch (type) {
case FruitTypeApple:
fruits = [[AppleFruit alloc]init];
break;
case FruitTypeOrange:
fruits = [[OrangeFruit alloc]init];
break;
default:
break;
}
return fruits;
}
@end
运行代码:
Fruits *fruit = [Fruits fruitsFactory:FruitTypeApple];
fruit.name = @"苹果";
[fruit sweet];
AppleFruit *apple = (AppleFruit*)[Fruits fruitsFactory:FruitTypeApple];
apple.name = @"苹果";
[apple freshApple];
简单工厂模式提供了专门的工厂类用于创建对象,将对象的创建和对象的使用分离开,它作为一种最简单的工厂模式在软件开发中得到了较为广泛的应用。
1)优点
工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责,而仅仅“消费”产品,简单工厂模式实现了对象创建和使用的分离。
客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度减少使用者的记忆量。
通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
2)缺点
由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。
系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
3)适用场景
工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
客户端只知道传入工厂类的参数,对于如何创建对象并不关心。
暂时先写到这,后续有时间再更新...