目录

  • 前言
  • 一、工厂模式简介
  • 二、简单工厂模式(Simple Factory)
  • 三、工厂方法模式(Factory Method)
  • 四、抽象工厂模式(Abstract Factory)
  • 五、模式的利弊

前言

设计模式算是一本非常基础的书籍,在无数程序员先驱的开发过程中总结了很多经验,提炼出了这20+的设计范式供大家参考。本系列文章是一次重新学习的过程,也是一次分享的过程,java版本的模式讲解已经非常多了,c++方面的资料确实要少一些,在原理上来讲设计模式无论是c++还是Java都是相通的,在这里我将会用c++来将设计模式实现一遍。实践出真知!

一、工厂模式简介

程序设计存在的问题:
1)为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共
接口以形成抽象基类或者接口
。这样我们可以通过声明一个指向基类的指针来指向实际的子
类实现,达到了多态的目的。这里很容易出现的一个问题 n 多的子类继承自抽象基类,我们
不得不在每次要用到子类的地方就编写诸如 new ×××;的代码。这里带来两个问题 1)客
户程序员必须知道实际子类的名称(当系统复杂后,命名将是一个很不好处理的问题,为了
处理可能的名字冲突,有的命名可能并不是具有很好的可读性和可记忆性,就姑且不论不同
程序员千奇百怪的个人偏好了。),2)程序的扩展性和维护变得越来越困难。

2)还有一种情况就是在父类中并不知道具体要实例化哪一个具体的子类。这里的意思
为:假设我们在类 A 中要使用到类 B,B 是一个抽象父类,在 A 中并不知道具体要实例化
那一个 B 的子类,但是在类 A 的子类 D 中是可以知道的。在 A 中我们没有办法直接使用类
似于 new ×××的语句,因为根本就不知道×××是什么。

以上两个问题也就引出了 Factory 模式的两个最重要的功能:
1)定义创建对象的接口,封装了对象的创建;
2)使得具体化类的工作延迟到了子类中。

二、简单工厂模式(Simple Factory)

  • 说明

我们通常使用 Factory 模式来解决上面给出的两个问题。在第一个问题中,我们经常声明一个创建对象的接口,并封装对象的创建过程。Factory 这里类似于一个真正意义上的工厂(生产对象)。在第二个问题中,我们需要提供一个对象创建对象的接口,并在子类中提供其具体实现(因为只有在子类中可以决定到底实例化哪一个类)。
第一中情况的 Factory 的结构示意图为:

下面我们使用手机生产来讲解该模式:
我们现在拥有两个品牌的手机需要生产,很显然两个品牌的手机拥有同样的基类,为了生产两种品牌的手机(生成对象),我们需要定义一个工厂类来专门负责生产手机的工作。

  • |__ phone.h:
#pragma once
#ifndef _Phone_H_
#define _Phone_H_
//Phone类:手机标准规范类(AbstractProduct)
class Phone
{public:virtual ~Phone() = 0;protected:Phone();
private:
};
// HuaweiPhone类:制造华为手机(Product1)
class HuaweiPhone :public Phone
{public:~HuaweiPhone();HuaweiPhone();void MakeHuaweiPhone();
protected:
private:
};
//IPhone类:制造苹果手机(Product2)
class IPhone :public Phone
{public:~IPhone();IPhone();void MakeIPhone();
protected:
private:
};
#endif //~_Phone_H_
  • |__ phone.cpp:
#include "Product.h"
#include <iostream>
using namespace std;
Phone::Phone()
{}
Phone::~Phone()
{}HuaweiPhone::HuaweiPhone()
{this->MakeHuaweiPhone();
}
HuaweiPhone::~HuaweiPhone()
{}
void HuaweiPhone::MakeHuaweiPhone()
{cout << "Make HuaweiPhone!"<<endl;
}IPhone::IPhone()
{this->MakeIPhone();
}
IPhone::~IPhone()
{}
void IPhone::MakeIPhone()
{cout << "Make IPhone!"<<endl;
}
  • |__ phoneFactory.h:
#pragma once
#ifndef _FACTORY_H_
#define _FACTORY_H_
#include <string>
class Phone;
//PhoneFactory类:手机代工厂(Factory)
class PhoneFactory
{public:virtual ~PhoneFactory();PhoneFactory();Phone* CreatePhone(std::string type);
protected:
private:
};
  • |__ phoneFactory.cpp:
#include "Factory.h"
#include "Product.h"
#include <iostream>
using namespace std;
PhoneFactory::PhoneFactory()
{}
PhoneFactory::~PhoneFactory()
{}
Phone* PhoneFactory::CreatePhone(string type)
{if (type == "HuaweiPhone") {return new HuaweiPhone();}else if (type == "IPhone") {return new IPhone();}return NULL;
}
  • |__ main.cpp:
#include "Factory.h"
#include "Product.h"#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{PhoneFactory *factory = new PhoneFactory();Phone *huaweiPhone= factory->CreatePhone("HuaweiPhone");            // make HuaweiPhone!IPhone *iPhone = (IPhone*)factory->CreatePhone("IPhone");          // make iphone!system("pause");return 0;
}

如上所示就实现了一个简单生产模式。

三、工厂方法模式(Factory Method)

  • 说明

上图所以的 Factory 模式经常在系统开发中用到,但是这并不是 Factory 模式的最大威力所在(因为这可以通过其他方式解决这个问题)。Factory 模式不单是提供了创建对象的接口,其最重要的是延迟了子类的实例化(第二个问题),以下是这种情况的一个 Factory 的结构示意图:

图 2 中关键中 Factory 模式的应用并不是只是为了封装对象的创建,而是要把对象的创建放到子类中实现:Factory 中只是提供了对象创建的接口,其实现将放在 Factory 的子类ConcreteFactory 中进行。这是图 2 和图 1 的区别所在。

接下来继续使用生产手机的例子来讲解该模式其中和产品相关的Phone类、HuaweiPhone类和IPhone类的定义不变。代码演示仅展示增量

  • |__ phoneFactory.h:
#pragma once
#ifndef _FACTORY_H_
#define _FACTORY_H_
#include <string>
class Phone;
class PhoneFactory
{public:virtual ~PhoneFactory();PhoneFactory();virtual Phone* CreatePhone() = 0;
protected:private:
};class HuaweiFactory :public PhoneFactory
{public:~HuaweiFactory();HuaweiFactory();Phone* CreatePhone();
protected:
private:
};class AppleFactory :public PhoneFactory
{public:~AppleFactory();AppleFactory();Phone* CreatePhone();
protected:
private:
};
#endif //~_FACTORY_H_
  • |__ phoneFactory.cpp:
#include "Factory.h"
#include "Product.h"
#include <iostream>
using namespace std;
PhoneFactory::PhoneFactory()
{}
PhoneFactory::~PhoneFactory()
{}HuaweiFactory::HuaweiFactory()
{}
HuaweiFactory::~HuaweiFactory()
{}
Phone* HuaweiFactory::CreatePhone()
{return new HuaweiPhone();
}AppleFactory::AppleFactory()
{}
AppleFactory::~AppleFactory()
{}
Phone* AppleFactory::CreatePhone()
{return new IPhone();
}
  • |__ main.cpp:
#include "Factory.h"
#include "Product.h"#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{PhoneFactory *huaweiFactory = new HuaweiFactory();PhoneFactory *appleFactory = new AppleFactory();Phone *HuaweiPhone = huaweiFactory->CreatePhone();IPhone *iPhone = (IPhone*)appleFactory->CreatePhone();system("pause");return 0;
}

四、抽象工厂模式(Abstract Factory)

上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品Phone(AbstractProduct),如果要生成另一种产品PC,应该怎么表示呢?

最简单的方式是把2中介绍的工厂方法模式完全复制一份,不过这次生产的是PC。但同时也就意味着我们要完全复制和修改Phone生产管理的所有代码,显然这是一个笨办法,并不利于扩展和维护

抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干。
其UML类图如下:

抽象工厂模式的实现也较为简单,此处就略去不表了。

五、模式的利弊

  • 工厂模式是为了解耦。可以将对象的创建和使用分离,如果不分离,不但违反了设计模式的开闭原则,需要需要使用另一个子类的话,需要修改源代码 ,把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只是调用B的方法,而至于B的实例化,就交给工厂类。

  • 工厂模式可以降低代码重复。如果创建对象B的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。我们可以这些创建对象B的代码放到工厂里统一管理。既减少了重复代码,也方便以后对B的创建过程的修改维护。(当然,我个人觉得也可以把这些创建过程的代码放到类的构造函数里,同样可以降低重复率,而且构造函数本身的作用也是初始化对象。不过,这样也会导致构造函数过于复杂,做的事太多,不符合java 的设计原则。)
    由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。同理,想把所有调用B的地方改成B的子类B1,只需要在对应生产B的工厂中或者工厂的方法中修改其生产的对象为B1即可,而不需要找到所有的new B()改为new B1()。

  • 因为工厂管理了对象的创建逻辑,使用者并不需要知道具体的创建过程,只管使用即可,减少了使用者因为创建逻辑导致的错误

  • 可以通过参数设置,返回不同的构造函数,不需要修改使用类的地方。如果一个类有多个构造方法(构造的重写),我们也可以将它抽出来,放到工厂中,一个构造方法对应一个工厂方法并命名一个友好的名字,这样我们就不再只是根据参数的不同来判断,而是可以根据工厂的方法名来直观判断将要创建的对象的特点。这对于使用者来说,体验比较好。

举个例子

一个数据库工厂:可以返回一个数据库实例,可以是mysql,oracle等。

这个工厂就可以把数据库连接需要的用户名,地址,密码等封装好,直接返回对应的数据库对象就好。不需要调用者自己初始化,减少了写错密码等等这些错误。调用者只负责使用,不需要管怎么去创建、初始化对象。

❤️❤️❤️ 如果本文对你有所帮助,请不要忘了点赞、关注、收藏哦!灰常感谢! ❤️❤️❤️

❤️ 工厂模式:教你如何制造一台Huawei P50手机 ❤️相关推荐

  1. 工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 工厂模式于抽象工厂的区别 设计模式

    工厂模式 定义一个用于创建对象的接口,让子类实现具体类的创建.工厂将类的实例化延迟的子类. 良好的分装性.对于具体产品,只要知道产品名称即可(类名或字符串),封闭了对产品创建的细节. 屏蔽具体产品类. ...

  2. 工厂模式--简单工厂模式--抽象工厂模式

    工厂模式 作用:实现创建者与调用者的分离 简单工厂模式.工厂方法模式.抽象工厂模式,都是属于创建型设计模式.严格上来说,简单工厂模式不属于23设计模式之一,因为它违背了开闭原则. ========== ...

  3. JAVA工厂模式优缺点_简单工厂模式、工厂模式和抽象工厂模式区别及优缺点

    各位小伙伴好,今天给大家主要介绍一下简单工厂模式.工厂模式和抽象工厂模式的区别及各自的优缺点. (本文实现语言为Python3) [前言] 众所周知今天所讲的内容是 设计模式的一类:对于设计模式这个概 ...

  4. 简单工厂模式、工厂模式和抽象工厂模式区别及优缺点

    各位小伙伴好,今天给大家主要介绍一下简单工厂模式.工厂模式和抽象工厂模式的区别及各自的优缺点. (本文实现语言为Python3) [前言] 众所周知今天所讲的内容是设计模式的一类:对于设计模式这个概念 ...

  5. 教你如何一篇博客读懂设计模式之—--工厂模式

    一篇博客读懂设计模式之-工厂模式 工厂模式在我们日常开发的时候经常用到,相信大家都有了一定的了解,工厂模式是一种创建对象的设计模式,它提供一种创建对象的最佳方式. 主要过程是: 定义一个创建对象的接口 ...

  6. 手把手教你应用三种工厂模式在SpringIOC中创建对象实例【案例详解】

    目录 一.工厂模式介绍 二.通过静态工厂方法创建Bean实例 三.通过实例工厂方法创建Bean实例 四.通过自定义的factoryBean来创建bean对象 Hello,你好呀,我是灰小猿!一个超会写 ...

  7. 结合案例深入解析:抽象工厂模式

    一.基本概念 当涉及到产品族的时候,就需要引入抽象工厂模式了. 每一个模式都是针对一定问题的解决方案.抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构:而抽象工厂模式则 ...

  8. 《Head First 设计模式》(四):工厂模式

    1.简单工厂模式 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 注意: 实际上简单工厂不是一个设计模式,更多程度上比较像一种编程习惯. 结构图: Factory ...

  9. 设计模式之工厂模式,史上最强,不服来辩!

    设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,如果设计模式没学会,抽象能力肯定就不会太强.常见的设计模式有 23 种,今天我们只聊最简单的工厂模式. 工厂模式是属于创建型模式的,通过工厂 ...

  10. (13)C#传智:访问修饰符,简单工厂模式,序列化与反序列化,部分类,密封类,接口(第13天)

    内容超级多,慢慢来... 深入BinaryFormatter 一.访问修饰符 public: 公共的,公开的     private:私有的,只能在当前类的内部访问     protected:受保持 ...

最新文章

  1. jieba之segment
  2. python文档生成工具_pydoc --- 文档生成器和在线帮助系统 — Python 3.9.1rc1 文档
  3. 数学之美 系列九 -- 如何确定网页和查询的相关性
  4. 【数据竞赛】DoubleEnsemble--专治硬样本的神奇集成技术。
  5. python中文开发环境_Python开发环境配置
  6. java常用代码总结
  7. Qt::WA_OpaquePaintEvent理解
  8. 使用Jasmine,Spock和Nashorn测试JVM服务器端JavaScript
  9. 数据库系统概论王珊编写的第三章学生-课程数据库
  10. linux修改可用的最大进程数量和可打开的最大文件数
  11. 编写一个能监控到windows进程占用内存大小的脚本_Java性能监控分析及调优工具...
  12. Ubuntu18.04下解决Qt出现qt.qpa.plugin:Could not load the Qt platform plugin “xcb“问题
  13. Python基于wordnet实现词语相似度计算分析
  14. 本科毕业论文EndNote格式
  15. 关于vs2015各版本的卸载
  16. matlab小波具体频段,一种小波包分解节点与对应频段检索及编程方法
  17. 成都计算机影响力高校,成都最好的三所大学,你更青睐哪一所?
  18. Mac pip confirming SSL certificate
  19. Android系统的Ashmem匿名共享内存子系统分析(4)- Ashmem子系统的 Java访问接口
  20. Web服务器搭建(一)

热门文章

  1. 微博宕机复盘:什么样的技术架构,可支持80个明星并发出轨?
  2. C语言因式分解的程序框图,C语言编写方案-因式分解
  3. RuntimeError: DataLoader worker (pid 4499) is killed by signal: Segmentation fault.检查内存条!
  4. export default function和export function的区别
  5. 微软bi报表服务器,为 Power BI 报表服务器创建 Power BI 报表
  6. 第一讲 OC简介及基本语法
  7. Android 通知用法
  8. 王二 设计模式读书笔记
  9. uva11045(最大二分图匹配)
  10. 基于C++的web服务器---总述篇