iOS学习笔记

工厂方法与抽象工厂的迷之理解

2018-08-06  本文已影响31人  王技术

听到抽象这个词
我想到了薛之谦的一句歌词
你不就像风一样
好不具象....


其实我也想着
有一天程序员做不下去了
头发也掉光了
就回老家
老婆孩子热炕头的
开一家花生油店
毕竟家里祖传的手艺不能丢
这样的话, 我首先就需要一个生产花生油实例的花生油类 : HXPeanutOil :

//HXPeanutOil.h

#import <Foundation/Foundation.h>

@interface HXPeanutOil : NSObject
- (void)smellSmell;
@end
// HXPeanutOil.m

#import "HXPeanutOil.h"

@implementation HXPeanutOil
- (void)smellSmell {
    NSLog(@"我是花生油, 我是花生油的味道");
}
@end

当然想要生产花生油
得有个小作坊, 也就是工厂

// HXPeanutOilFactory.h

#import <Foundation/Foundation.h>
#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 <Foundation/Foundation.h>
#import "HXOil.h"

@interface HXOilFactory : NSObject
+ (HXOil *)createOil;
@end

// HXOilFactory.m

#import "HXOilFactory.h"

@implementation HXOilFactory
+ (HXOil *)createOil {
    return nil;
}
@end

于是
抽象产品也就诞生了 :

// HXOil.h

#import <Foundation/Foundation.h>

@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 <Foundation/Foundation.h>
#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 <Foundation/Foundation.h>

@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 <Foundation/Foundation.h>

@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 和油桶
刚才创建的油厂就不能产这些东西了, 就要重新建厂
一般来说,产品种类单一,适合用工厂模式
如果有多个种类,各种类型时,通过抽象工厂模式来进行创建是很合适的。

这里是代码
我理解的有点糙
有不对的地方, 还望大神指正
喜欢请点个赞
祝大家早日富可敌国

上一篇下一篇

猜你喜欢

热点阅读