美文网首页iOS学习笔记
工厂方法与抽象工厂的迷之理解

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

作者: 王技术 | 来源:发表于2018-08-06 21:29 被阅读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 和油桶
    刚才创建的油厂就不能产这些东西了, 就要重新建厂
    一般来说,产品种类单一,适合用工厂模式
    如果有多个种类,各种类型时,通过抽象工厂模式来进行创建是很合适的。

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

    相关文章

      网友评论

      本文标题:工厂方法与抽象工厂的迷之理解

      本文链接:https://www.haomeiwen.com/subject/dxogvftx.html