专栏首页程序员维他命面向对象设计的设计模式(二):工厂方法模式

面向对象设计的设计模式(二):工厂方法模式

继上一篇简单工厂模式,本篇讲解的是创建型设计模式中的工厂方法模式。

定义

工厂方法模式(Factory Method Pattern)又称为工厂模式,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过不同的工厂子类来创建不同的产品对象。

适用场景

工厂方法模式的适用场景与简单工厂类似,都是创建数据和行为比较类似的对象。但是和简单工厂不同的是:在工厂方法模式中,因为创建对象的责任移交给了抽象工厂的子类,因此客户端需要知道其所需产品所对应的工厂子类,而不是简单工厂中的参数。

下面我们看一下工厂方法模式的成员和类图。

成员与类图

成员

工厂方法模式包含四个成员:

  1. 抽象工厂(Abstract Factory):抽象工厂负责声明具体工厂的创建产品的接口。
  2. 具体工厂(Concrete Factory):具体工厂负责创建产品。
  3. 抽象产品(Abstract Product):抽象产品是工厂所创建的所有产品对象的父类,负责声明所有产品实例所共有的公共接口。
  4. 具体产品(Concrete Product):具体产品是工厂所创建的所有产品对象类,它以自己的方式来实现其共同父类声明的接口。

下面通过类图来看一下各个成员之间的关系:

模式类图

工厂方法模式类图

从类图中我们可以看到:抽象工厂负责定义具体工厂必须实现的接口,而创建产品对象的任务则交给具体工厂,由特定的子工厂来创建其对应的产品。

这使得工厂方法模式可以允许系统在不修改原有工厂的情况下引进新产品:只需要创建新产品类和其所对应的工厂类即可。

代码示例

场景概述

同样也是模拟上面的简单工厂例子中的场景(手机商店卖手机),但是由于这次是由工厂方法模式来实现的,因此在代码设计上会有变化。

场景分析

与简单工厂模式不同的是:简单工厂模式里面只有一个工厂,而工厂方法模式里面有一个抽象工厂和继承于它的具体工厂。

因此同样的三个品牌的手机,我们可以通过三个不同的具体工厂:苹果手机工厂(IPhoneFactory),小米手机工厂 (MIPhoneFactory),华为手机工厂(HWPhoneFactory)来生产。而这些具体工厂类都会继承于抽象手机工厂类:PhoneFactory,它来声明生产手机的接口。

下面我们用代码来具体来看一下工厂类(抽象工厂和具体工厂)的设计:

代码实现

首先我们声明一个抽象工厂类 PhoneFactory

//================== PhoneFactory.h ==================
#import "Phone.h"

@interface PhoneFactory : NSObject

+ (Phone *)createPhone;

@end


//================== PhoneFactory.m ==================
@implementation PhoneFactory

+ (Phone *)createPhone{
    //implemented by subclass
    return nil;
}

@end

抽象工厂类给具体工厂提供了生产手机的接口,因此不同的具体工厂可以按照自己的方式来生产手机。下面看一下具体工厂:

苹果手机工厂 IPhoneFactory

//================== IPhoneFactory.h ==================
@interface IPhoneFactory : PhoneFactory
@end


//================== IPhoneFactory.m ==================
#import "IPhone.h"

@implementation IPhoneFactory

+ (Phone *)createPhone{

    IPhone *iphone = [[IPhone alloc] init];
    NSLog(@"iPhone has been created");
    return iphone;
}

@end

小米手机工厂 MIPhoneFactory

//================== MIPhoneFactory.h ==================
@interface MPhoneFactory : PhoneFactory

@end



//================== MIPhoneFactory.m ==================
#import "MiPhone.h"

@implementation MPhoneFactory

+ (Phone *)createPhone{

    MiPhone *miPhone = [[MiPhone alloc] init];
    NSLog(@"MIPhone has been created");
    return miPhone;
}

@end

华为手机工厂 HWPhoneFactory:

//================== HWPhoneFactory.h ==================
@interface HWPhoneFactory : PhoneFactory

@end



//================== HWPhoneFactory.m ==================
#import "HWPhone.h"

@implementation HWPhoneFactory

+ (Phone *)createPhone{

    HWPhone *hwPhone = [[HWPhone alloc] init];
    NSLog(@"HWPhone has been created");
    return hwPhone;
}

@end

以上就是声明的抽象工厂类和具体工厂类。因为生产手机的责任分配给了各个具体工厂类,因此客户端只需要委托所需手机所对应的工厂就可以获得其生产的手机了。

因为抽象产品类Phone和三个具体产品类(IPhoneMIPhoneHWPhone)和简单工厂模式中介绍的例子中的一样,因此这里就不再重复介绍了。

下面我们用代码模拟一下该场景:

//================== Using by client ==================


//A phone store
Store *phoneStore = [[Store alloc] init];

//phoneStore wants to sell iphone
Phone *iphone = [IPhoneFactory  createPhone];
[iphone packaging];
[phoneStore sellPhone:iphone];


//phoneStore wants to sell MIPhone
Phone *miPhone = [MPhoneFactory createPhone];
[miPhone packaging];
[phoneStore sellPhone:miPhone];

//phoneStore wants to sell HWPhone
Phone *hwPhone = [HWPhoneFactory createPhone];
[hwPhone packaging];
[phoneStore sellPhone:hwPhone];

由上面的代码可以看出:客户端phoneStore只需委托iPhone,MIPhone,HWPhone对应的工厂即可获得对应的手机了。

而且以后如果增加其他牌子的手机,例如魅族手机,就可以声明一个魅族手机类和魅族手机的工厂类并实现createPhone这个方法即可,而不需要改动原有已经声明好的各个手机类和具体工厂类。

下面我们看一下该例子对应的 UML类图,可以更直观地看一下各个成员之间的关系:

代码对应的类图

工厂方法模式代码示例类图

优点

  • 用户只需要关心其所需产品对应的具体工厂是哪一个即可,不需要关心产品的创建细节,也不需要知道具体产品类的类名。
  • 当系统中加入新产品时,不需要修改抽象工厂和抽象产品提供的接口,也无须修改客户端和其他的具体工厂和具体产品,而只要添加一个具体工厂和与其对应的具体产品就可以了,符合了开闭原则(这一点与简单工厂模式不同)。

缺点

  • 当系统中加入新产品时,除了需要提供新的产品类之外,还要提供与其对应的具体工厂类。因此系统中类的个数将成对增加,增加了系统的复杂度。

iOS SDK 和 JDK 中的应用

  • 暂未发现iOS SDK中使用工厂方法的例子,有知道的小伙伴欢迎留言。
  • 在JDK中,Collection接口声明了iterator()方法,该方法返回结果的抽象类是IteratorArrayList就实现了这个接口;,而ArrayList对应的具体产品是Itr

本文分享自微信公众号 - 程序员维他命(J_Knight_),作者:维他命君

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-11-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 面向对象设计的设计模式(三):抽象工厂模式

    有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。比如系统中有多于一个的产品族,而每次只使用其中某一产品族,属于同一个产品族的产品将在一起使用。

    用户2932962
  • 老司机 iOS 周报 #79 | 2019-08-12

    你也可以为这个项目出一份力,如果发现有价值的信息、文章、工具等可以到 Issues 里提给我们,我们会尽快处理。记得写上推荐的理由哦。有建议和意见也欢迎到 Is...

    用户2932962
  • 面向对象设计的设计模式(十六):状态模式

    如果我们通过if else来判断对象的状态,那么代码中会包含大量与对象状态有关的条件语句,而且在添加,删除和更改这些状态的时候回比较麻烦;而如果使用状态模式。将...

    用户2932962
  • 面向对象设计的设计模式(二):工厂方法模式

    工厂方法模式的适用场景与简单工厂类似,都是创建数据和行为比较类似的对象。但是和简单工厂不同的是:在工厂方法模式中,因为创建对象的责任移交给了抽象工厂的子类,因此...

    用户1740424
  • 设计模式之静态工厂、工厂方法和抽象工厂的联系与区别

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

    大黄大黄大黄
  • 工厂方法模式(Factory Method)-最易懂的设计模式解析

    在上文提到的最易懂的设计模式系列解析:简单工厂模式,发现简单工厂模式存在一系列问题:

    Carson.Ho
  • 23种设计模式之工厂方法模式

    定义: 定义一个用于创建对象的接口,让子类决定实例化哪一个类. 工厂方法使一个类的实例化延迟到其子类

    烟草的香味
  • Python设计模式(2):工厂方法模式

    为了克服简单工厂方法模式的缺点,人们试图改善工厂类的结构。导致简单工厂方法模式不符合开闭原则的原因是工厂方法类只是一个实类,每当有一个新的产品类被加入到产品类的...

    不可言诉的深渊
  • 实时大数据开发实践

    本文主要从大数据起源谈起,介绍了几种主要的大数据处理框架,包括其中的容错机制,实现细节及原理等。再主要介绍了使用storm进行大数据开发的具体过程,以及开发过程...

    gaofc
  • 《三国演义》人物数据分析

    1.由于要分析120回中主要人物的出场次数,爬取《三国演义》120回,每回放在一个段落里;len(f.readlines()) = 120. 2.安装主要的py...

    Crossin先生

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动