前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >学会工厂方法模式,搬起砖头更加给力!

学会工厂方法模式,搬起砖头更加给力!

作者头像
用户6557940
发布2022-07-24 16:36:00
1530
发布2022-07-24 16:36:00
举报
文章被收录于专栏:Jungle笔记Jungle笔记

引言

在介绍简单工厂方法模式时Jungle总结出简单工厂模式存在最大的问题是违背了“开闭原则”,每当增加新的产品时,需要修改工厂类的逻辑。为了规避这种不足,同时很好的利用简单工厂模式的优点,本节Jungle将声情并茂地为您奉上工厂方法模式。

01

工厂方法模式简介

简单工厂模式中,每新增一个具体产品,就需要修改工厂类内部的判断逻辑。为了不修改工厂类,遵循开闭原则,工厂方法模式中不再使用工厂类统一创建所有的具体产品,而是针对不同的产品设计了不同的工厂,每一个工厂只生产特定的产品。

工厂方法模式定义:

工厂方法模式: 定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。

02

工厂方法模式结构

从工厂方法模式简介中,可以知道该模式有以下几种角色:

  • 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
  • 具体工厂(ConcreteFactory):生产具体的产品
  • 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
  • 具体产品(ConcreteProduct):具体的产品类

工厂方法模式UML类图如下:

03

代码实例

考虑这样一个场景,如下图:

Jungle想要进行户外运动,它可以选择打篮球、踢足球或者玩排球。和上一次的体育保管室不同,这次分别由篮球保管室、足球保管室和排球保管室,Jungle只需直接去相应的保管室就可以拿到对应的球!然后Jungle就可以愉快地玩耍了。

对应的UML实例图如下图:

定义抽象产品类AbstractSportProduct,方法不提供实现

代码语言:javascript
复制
//抽象产品类AbstractProduct
class AbstractSportProduct
{
public:
  AbstractSportProduct(){

  }
  //抽象方法:
  void printName(){};
  void play(){};
};

定义三个具体产品类

代码语言:javascript
复制
//具体产品类Basketball
class Basketball :public AbstractSportProduct
{
public:
  Basketball(){
    printName();
    play();
  }
  //具体实现方法
  void printName(){
    printf("Jungle get Basketball\n");
  }
  void play(){
    printf("Jungle play Basketball\n\n");
  }
};

//具体产品类Football
class Football :public AbstractSportProduct
{
public:
  Football(){
    printName();
    play();
  }
  //具体实现方法
  void printName(){
    printf("Jungle get Football\n");
  }
  void play(){
    printf("Jungle play Football\n\n");
  }
};

//具体产品类Volleyball
class Volleyball :public AbstractSportProduct
{
public:
  Volleyball(){
    printName();
    play();
  }
  //具体实现方法
  void printName(){
    printf("Jungle get Volleyball\n");
  }
  void play(){
    printf("Jungle play Volleyball\n\n");
  }
};

定义抽象工厂类AbstractFactory,方法为纯虚方法

代码语言:javascript
复制
//抽象工厂类
class AbstractFactory
{
public:
  virtual AbstractSportProduct *getSportProduct() = 0;
};

定义三个具体工厂类

代码语言:javascript
复制
/具体工厂类BasketballFactory
class BasketballFactory :public AbstractFactory
{
public:
  BasketballFactory(){
    printf("BasketballFactory\n");
  }
  AbstractSportProduct *getSportProduct(){
    printf("basketball");
    return new Basketball();
  }
};

//具体工厂类FootballFactory
class FootballFactory :public AbstractFactory
{
public:
  FootballFactory(){
    printf("FootballFactory\n");
  }
  AbstractSportProduct *getSportProduct(){
    return new Football();
  }
};

//具体工厂类VolleyballFactory
class VolleyballFactory :public AbstractFactory
{
public:
  VolleyballFactory(){
    printf("VolleyballFactory\n");
  }
  AbstractSportProduct *getSportProduct(){
    return new Volleyball();
  }
};

客户端使用方法示例

代码语言:javascript
复制
#include <iostream>
#include "FactoryMethod.h"

int main()
{
  printf("工厂方法模式\n");

  //定义工厂类对象和产品类对象
  AbstractFactory *fac = NULL;
  AbstractSportProduct *product = NULL;

  fac = new BasketballFactory();
  product = fac->getSportProduct();

  fac = new FootballFactory();
  product = fac->getSportProduct();

  fac = new VolleyballFactory();
  product = fac->getSportProduct();

  system("pause");
  return 0;
}

效果

04

总结

如果Jungle想玩棒球(Baseball),只需要增加一个棒球工厂(BaseballFacory),然后在客户端代码中修改具体工厂类的类名,而原有的类的代码无需修改。由此可看到,相较简单工厂模式,工厂方法模式更加符合开闭原则。工厂方法是使用频率最高的设计模式之一,是很多开源框架和API类库的核心模式。

优点:

  • 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
  • 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂方法模式的关键;
  • 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则。

缺点:

  • 添加新产品时需要同时添加新的产品工厂,系统中类的数量成对增加,增加了系统的复杂度,更多的类需要编译和运行,增加了系统的额外开销;
  • 工厂和产品都引入了抽象层,客户端代码中均使用的抽象层(AbstractFactory和AbstractSportProduct ),增加了系统的抽象层次和理解难度。

适用环境:

  • 客户端不需要知道它所需要创建的对象的类;
  • 抽象工厂类通过其子类来指定创建哪个对象(运用多态性设计和里氏代换原则)

设计模式系列代码地址:https://github.com/FengJungle/DesignPattern

·END·

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Jungle笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义抽象产品类AbstractSportProduct,方法不提供实现
  • 定义三个具体产品类
  • 定义抽象工厂类AbstractFactory,方法为纯虚方法
  • 效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档