-
工厂方法
其实我也想着
有一天程序员做不下去了
头发也掉光了
就回老家
老婆孩子热炕头的
开一家花生油店
毕竟家里祖传的手艺不能丢
这样的话, 我首先就需要一个生产花生油实例的花生油类 : HXPeanutOil :
//HXPeanutOil.h
#import
@interface HXPeanutOil : NSObject
- (void)smellSmell;
@end
// HXPeanutOil.m
#import "HXPeanutOil.h"
@implementation HXPeanutOil
- (void)smellSmell {
NSLog(@"我是花生油, 我是花生油的味道");
}
@end
当然想要生产花生油
得有个小作坊, 也就是工厂
// HXPeanutOilFactory.h
#import
#import "HXPeanutOil.h"
@interface HXPeanutOilFactory : NSObject
+ (HXPeanutOil *)createOil;
@end
// HXPeanutOilFactory.m
#import "HXPeanutOilFactory.h"
@implementation HXPeanutOilFactory
+ (HXPeanutOil *)createOil {
return [[HXPeanutOil alloc] init];
}
@end
这样基本就可以开工了
但是!
作为一个头发都秃光了的资深程序员
怎么能如此目光短浅
只生产花生油呢
哪天客户要我生产玉米油咋整
学以致用
继承搞起来
多态搞起来
于是
抽象工厂就诞生了 :
// HXOilFactory.h
#import
#import "HXOil.h"
@interface HXOilFactory : NSObject
+ (HXOil *)createOil;
@end
// HXOilFactory.m
#import "HXOilFactory.h"
@implementation HXOilFactory
+ (HXOil *)createOil {
return nil;
}
@end
于是
抽象产品也就诞生了 :
// HXOil.h
#import
@interface HXOil : NSObject
- (void)smellSmell;
@end
// HXOil.m
#import "HXOil.h"
@implementation HXOil
- (void)smellSmell {
}
@end
让之前花生油工厂 HXPeanutOilFactory 继承抽象工厂 HXOilFactory, 并把的生产操作 createOil 提取到父类
让之前花生油产品 HXPeanutOil 继承抽象产品 HXOil, 并把的闻一闻操作 smellSmell 提取到父类
这样的话, 看起来舒适很多
如果这时候花生油生意做大了
出于对我产油能力的肯定, 客户非要我生产玉米油
这样的话玉米油工厂只需要继承 HXOilFactory 创建 HXMaizeOilFactory
公用的生产操作已经在父类中声明
// HXMaizeOilFactory.h
#import "HXOilFactory.h"
@interface HXMaizeOilFactory : HXOilFactory
@end
// HXMaizeOilFactory.m
#import "HXMaizeOilFactory.h"
#import "HXMaizeOil.h"
@implementation HXMaizeOilFactory
+ (HXMaizeOil *)createOil {
return [[HXMaizeOil alloc] init];
}
@end
然后玉米油就是继承 HXOil 的 HXMaizeOil
同样公用的闻一闻操作也已经在父类中已经声明
// HXMaizeOil.h
#import "HXOil.h"
@interface HXMaizeOil : HXOil
@end
// HXMaizeOil.m
#import "HXMaizeOil.h"
@implementation HXMaizeOil
- (void)smellSmell {
NSLog(@"我是玉米油, 我是玉米油的味道");
}
@end
这样以来
就可以完美的生产出玉米油
客户只需要像让我生产花生油那样
告诉我生产玉米油
就可以生产玉米油了
不需要客户端做额外操作
如果客户有一天觉得这些油都不好吃了
想尝一尝地沟油
那么只需要继承 HXOilFactory 创建地沟油工厂类
继承 HXOil 创建地沟油产品类
就可以生产地沟油给客户啦
例如生产玉米油, 大概就像这个样子 :
- (void)createMaizeOil {
HXOil *oil = [HXMaizeOilFactory createOil];
[oil smellmell];
}
总结 :
工厂方法模式中的参与者:
抽象工厂角色:工厂模式的基类,定义了公共接口
具体工厂角色:实现了抽象工厂类的接口,是与客户端直接交互的类,负责具体的产品对象的创建
抽象产品角色:是具体产品类的基类,定义了公共接口
具体产品角色:实现了抽象产品类接口,每一个具体产品类都会对应一个工厂
-
抽象工厂
发现回到家之后
油坊火了
实现财富自由了
没办法啊,怎么办呢?
创品牌吧!
品牌就叫撸花花生油
然后又给自己的品牌设计了
一个个性油桶和一个个性 Logo
油桶和 Logo 哪里来?
自产!
要生产油桶和 Logo
也得要工厂啊
瞅了瞅自己的花生油玉米油和地沟油的油厂
油厂只能生产油
想让油厂产油桶和 logo 估计也不好使
重新建厂! 有钱!
软件设计的黄金法则 : 变动需要抽象!
于是抽象工厂 HXOilAccessoryFactory 类诞生了 :
// HXOilAccessoryFactory.h
#import
#import "HXOilLogo.h"
#import "HXOilContainer.h"
typedef NS_ENUM(NSUInteger, HXOilType) {
/** 撸花花生油 */
HXOilTypeLuHuaOil
};
@interface HXOilAccessoryFactory : NSObject
+ (HXOilAccessoryFactory *)factoryWithType:(HXOilType)type;
- (HXOilLogo *)createOilLogo;
- (HXOilContainer *)createilContainer;
@end
// HXOilAccessoryFactory.m
#import "HXOilAccessoryFactory.h"
#import "HXLuHuaOilAccessoryFactory.h"
@implementation HXOilAccessoryFactory
+ (HXOilAccessoryFactory *)factoryWithType:(HXOilType)type {
if (type == HXOilTypeLuHuaOil) {
return [[HXLuHuaOilAccessoryFactory alloc] init];
}else {
return nil;
}
}
- (HXOilLogo *)createOilLogo {
return nil;
}
- (HXOilContainer *)createilContainer {
return nil;
}
@end
这个类干这么2件事 :
根据客户需求, 返回具体工厂
声明了每个具体工厂都需要实现的接口(生产 Logo 接口,和生产油桶接口)
然后就是我们创的品牌撸花花生油的具体工厂
继承自 HXOilAccessoryFactory 的 HXLuHuaOilAccessoryFactory
// HXLuHuaOilAccessoryFactory.h
#import "HXOilAccessoryFactory.h"
@interface HXLuHuaOilAccessoryFactory : HXOilAccessoryFactory
@end
// HXLuHuaOilAccessoryFactory.m
#import "HXLuHuaOilAccessoryFactory.h"
#import "HXLuHuaOilLogo.h"
#import "HXLuHuaOilContainer.h"
@implementation HXLuHuaOilAccessoryFactory
- (HXOilLogo *)createOilLogo {
return [[HXLuHuaOilLogo alloc] init];
}
- (HXOilContainer *)createilContainer {
return [[HXLuHuaOilContainer alloc] init];
}
@end
他用来生产实体 Logo 和实体油桶
生产出的油桶是 HXLuHuaOilContainer
Logo 就是 HXLuHuaOilLogo
HXLuHuaOilContainer 继承抽象产品类 HXOilContainer
HXLuHuaOilLogo 继承抽象产品类 HXOilLogo
他们的实现分别如下 :
// HXOilLogo.h
// Logo 的抽象父类
#import
@interface HXOilLogo : NSObject
- (void)color;
- (void)appearance;
@end
// HXOilLogo.m
#import "HXOilLogo.h"
@implementation HXOilLogo
- (void)color {
}
- (void)appearance {
}
@end
// HXLuHuaOilLogo.h
// 我是撸花花生油 Logo 的实体类
#import "HXOilLogo.h"
@interface HXLuHuaOilLogo : HXOilLogo
@end
// HXLuHuaOilLogo.m
#import "HXLuHuaOilLogo.h"
@implementation HXLuHuaOilLogo
- (void)color {
NSLog(@"我是撸花花生油 Logo, 我是黄色");
}
- (void)appearance {
NSLog(@"我是撸花花生油 Logo, 我是三角形");
}
@end
// HXOilContainer.h
// 油桶 OilContainer 的抽象父类
#import
@interface HXOilContainer : NSObject
- (void)name;
- (void)size;
@end
// HXOilContainer.m
#import "HXOilContainer.h"
@implementation HXOilContainer
- (void)name {
}
- (void)size {
}
@end
// HXLuHuaOilContainer.h
// 撸花花生油的油桶实体类
#import "HXOilContainer.h"
@interface HXLuHuaOilContainer : HXOilContainer
@end
// HXLuHuaOilContainer.m
#import "HXLuHuaOilContainer.h"
@implementation HXLuHuaOilContainer
- (void)name {
NSLog(@"我是撸花花生油油桶");
}
- (void)size {
NSLog(@"我是撸花花生油油桶 -- 我能装3L");
}
@end
对于 Logo
他有 color 和 appearance 两个操作
都已在抽象父类中声明
实体子类来具体实现
对于 OilContainer
他有 name 和 size 两个操作
都已在抽象父类中声明
实体子类来具体实现
客户端的调用 :
- (void)abstractFactory {
HXOilAccessoryFactory *factory = [HXOilAccessoryFactory factoryWithType:HXOilTypeLuHuaOil];
HXOilLogo *logo = [factory createOilLogo];
HXOilContainer *container = [factory createilContainer];
[logo color];
[logo appearance];
[container name];
[container size];
}
打印是这个样子 :
2018-08-07 16:25:40.115446+0800 我是撸花花生油 Logo, 我是黄色
2018-08-07 16:25:40.115597+0800 我是撸花花生油 Logo, 我是三角形
2018-08-07 16:25:40.115894+0800 我是撸花花生油油桶
2018-08-07 16:25:40.115974+0800 我是撸花花生油油桶 -- 我能装3L
到此为止
已经可以完美的生产撸花花生油的 Logo 和油桶(OilContainer)了
可是久而久之
客户吃够了撸花花生油
没办法, 他们总是喜新厌旧的
然后客户提出了新需求 : 我还是想吃地沟油
怎么办呢?
产啊, 地沟油油桶, 地沟油 Logo 都要产
先建厂 HXDiGouOilAccessoryFactory 继承自刚才的抽象工厂 HXOilAccessoryFactory
// HXDiGouOilAccessoryFactory.h
#import "HXOilAccessoryFactory.h"
@interface HXDiGouOilAccessoryFactory : HXOilAccessoryFactory
@end
// HXDiGouOilAccessoryFactory.m
#import "HXDiGouOilAccessoryFactory.h"
#import "HXDiGouOilLogo.h"
#import "HXDiGouOilContainer.h"
@implementation HXDiGouOilAccessoryFactory
- (HXOilLogo *)createOilLogo {
return [[HXDiGouOilLogo alloc] init];
}
- (HXOilContainer *)createilContainer {
return [[HXDiGouOilContainer alloc] init];
}
@end
然后创建产品 HXDiGouOilLogo 继承自 HXOilLogo
然后创建产品 HXDiGouOilContainer 继承自 HXOilContainer
实现如下 ;
// HXDiGouOilLogo.h
// 我是地沟油 Logo
#import "HXOilLogo.h"
@interface HXDiGouOilLogo : HXOilLogo
@end
// HXDiGouOilLogo.m
#import "HXDiGouOilLogo.h"
@implementation HXDiGouOilLogo
- (void)color {
NSLog(@"我是地沟油 Logo, 我是棕色");
}
- (void)appearance {
NSLog(@"我是地沟油 Logo, 我是心形");
}
@end
// HXDiGouOilContainer.h
// 地沟油的油桶
#import "HXOilContainer.h"
@interface HXDiGouOilContainer : HXOilContainer
@end
// HXDiGouOilContainer.m
#import "HXDiGouOilContainer.h"
@implementation HXDiGouOilContainer
- (void)name {
NSLog(@"我是地沟油油桶");
}
- (void)size {
NSLog(@"我是地沟油油桶 -- 我能装50L");
}
@end
调用的话 就可以这么搞 :
//抽象工厂
- (void)abstractFactory {
HXOilAccessoryFactory *factory = [HXOilAccessoryFactory factoryWithType:HXOilTypeDiGouOil];
HXOilLogo *logo = [factory createOilLogo];
HXOilContainer *container = [factory createilContainer];
[logo color];
[logo appearance];
[container name];
[container size];
}
打印将是这样 :
2018-08-07 16:53:18.718973+0800 我是地沟油 Logo, 我是棕色
2018-08-07 16:53:18.719095+0800 我是地沟油 Logo, 我是心形
2018-08-07 16:53:18.719209+0800 我是地沟油油桶
2018-08-07 16:53:18.719333+0800 我是地沟油油桶 -- 我能装50L
到这里为止
已经可以完美的生产地沟油
满足了客户想吃地沟油的心情
思路大概就是这样
以后增加新品种
就建新厂
搞新产品
抽象工厂的总结以及与工厂方法的区别 :
抽象工厂模式提供一个创建一系列相关或相互依赖的对象的接口
而无需指定它们具体的类(就像我们创建的具体工厂实例, 都是用抽象工厂的指针指向他, 其实指针并不知道自己指向的是地沟油实例, 还是花生油实例)
那么工厂模式和抽象工厂模式的区别是什么呢?
这两种设计模式主要的区别在于产品
工厂模式是用来创建同一个产品的不同类型
比如说产油, 花生油, 玉米油, 地沟油, 都是油
但是抽象工厂模式是用来创建一系列相关不同类型的产品
比如油坊还想自己产一些 Logo 和油桶
刚才创建的油厂就不能产这些东西了, 就要重新建厂
一般来说,产品种类单一,适合用工厂模式
如果有多个种类,各种类型时,通过抽象工厂模式来进行创建是很合适的。
这里是代码
我理解的有点糙
有不对的地方, 还望大神指正
感谢阅读
你的支持是我写作的唯一动力
享元模式
建造者模式
中介者模式