工程实践之路:c++接口设计中的工厂模型(代码片段)

CodeBowl CodeBowl     2023-01-23     722

关键词:


上一篇文章写了 《工程实践:C++接口设计指北》
主要写了用C++写第三库,如何设计接口的问题,其中用到了工厂模式,在此之前,一直不太明白《设计模式》在实际开发中的应用。
现在正好被我逮到了,以此为例,深入学习一下!

设计模式之工厂模式

工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。

工厂设计模式是为了将对象的创建与使用进行分离 。(这段话是本文的重点)
在上文,我们接口设计主要目的也是这个;接口是实现多重继承的途径(这个知识点,在面试的时候,一定会被问道多态和虚函数),而生成遵循某个接口的对象的典型方法就是工厂方法的设计模式,这和直接调用构造函数不同,我们在工厂对象中调用的是创建函数,而该工厂对象将生成接口的某个实现对象。

在理论层面上,通过这种方法我们达到接口和代码实现分离的目标。

为什么使用工厂模式

1.工厂设计模式是为了将对象的创建与使用进行分离

这句话第二次被提到。
其实这句话,再抽象一下就是降低模块间的耦合度。

我们举个例子:
现在有俩个模块:模块A、模块B
其中模块A有很多子模块继承于模块A,模块A_1、模块A_2…模块A_n,这些模块都有一个共同的接口。
此时,模块B要调用模块A的子模块的方法,需要写成module_A1->interface()或者 module_An->interface();
这时候模块B中充满了模块A子模块的实例,两个模块高度耦合,而且使用接口的地方代码重复率很高。

我们想到了改进,使用多态,mode *A = new module_A1(); A->interface();虽然这种情况解决了模块B中多个模块A子模块的问题,只要一个模块A实例,降低了耦合度。

但是还有一个问题,那就是模块B每次调用都还要知道,具体实例化哪个A的子模块,同时模块A添加修改了子模块,模块B也要修改;
但是模块B并不想操心那么多,于是模块B说:“我只想无脑用这个接口罢了”,此时模块A说:“没问题,这个交给我来解决,以后你只要调用下面这个接口,其它交给我来办”,这是模块B开心的笑了,嗯嗯,这样多简单啊。

 Factory* factory = new Factory();

 factory->Create(xxx)->interface();

此时模块A和模块B之间的耦合度基本很小了,上面的factory,就是我们常说的工厂模式了,工厂会根据参数自动创建对应的模块A子模块实例,它主要是用来减少两个模块间的耦合度的,调用者不需要管你是怎么创建的对象,调用者只负责拿来用就行。

2.其他好处

减少代码的维护难度,增加代码的可阅读性。

简单工厂模式

简单工厂模式举个直白的例子就是,好比一个手机制造工厂,里面有几条手机制造生产线,我们只要给了对应的材料,就能制造出对应的手机。
代码示例:

#include <iostream>
using namespace std; 
 
enum phoneType 
    miType = 0,
    huaweiType,
    oppoType
;
 
class phone 
    public:
        virtual void show()=0; 
; 
 
class mi:public phone
    public:   
        void show() 
            cout<<"mi phone create"<<endl;
        
;
 
class huawei: public phone 
    public:
        void show() 
            cout<<"huawei phone create"<<endl;
        
;
 
class oppo: public phone 
    public:
        void show() 
            cout<<"oppo phone create"<<endl;
        
;
#if 1
class Factory 
    public:
        phone*  createPhone(enum phoneType type) 
            if(type == miType) 
                return new mi();
             else if (type == huaweiType) 
                return new huawei();
             else if (type == oppoType)
                return new oppo();
             else 
                return NULL;
            
         
;
#endif
int main() 
    Factory *f = new Factory();
    f->createPhone(miType)->show();
    f->createPhone(huaweiType)->show();
    f->createPhone(oppoType)->show();
    delete f;
    return 0;

上面的代码就是简单工厂模式,但是这有个问题,就是当工厂目前不满足于只生产这三种手机,还想在生产vivo,那就需要在工厂里面添加一条生产线,也就是修改Factory的代码逻辑,这违背了程序设计的开放封闭原则,我们应当以添加代码解决方法,尽可能不改变原有的代码。于是就有了参数工厂方法。

工厂方法模式

我们可以通过创建一个Factory的子类来通过多态实现这一点,但是这是以新建一个类作为代价的。每次添加一个类就要创建一个工厂子类,这样的好处是不用改变原有的工厂,在实现中我们可以通过参数化工厂方法,即给FactoryMethod()传递一个参数用以决定是创建具体哪一个具体的类。
以后如果赚钱了,想再造个1+手机,直接再建一个1+工厂,不需要动其它手机的工厂逻辑了,简单的用代码实现如下:

#include <iostream>
using namespace std; 
 
enum phoneType 
    miType = 0,
    huaweiType,
    oppoType,
    vivoType
;
 
class phone 
    public:
        virtual void show()=0; 
; 
 
class mi:public phone
    public:   
        void show() 
            cout<<"mi phone create"<<endl;
        
;
 
class huawei: public phone 
    public:
        void show() 
            cout<<"huawei phone create"<<endl;
        
;
 
class oppo: public phone 
    public:
        void show() 
            cout<<"oppo phone create"<<endl;
        
;
 
class vivo: public phone 
    public:
        void show() 
            cout<<"vivo phone create"<<endl;
        
;
 
class Factory 
    public:
       virtual  phone* createPhone()  = 0;
;
 
class miFactory:public Factory 
    public:
        phone* createPhone() 
            return new mi();
        
;
 
class huaweiFactory:public Factory 
    public:
        phone* createPhone() 
            return new huawei();
        
;
 
class oppoFactory:public Factory 
    public:
        phone* createPhone() 
            return new oppo();
        
;
 
class vivoFactory:public Factory 
    public:
        phone* createPhone() 
            return new vivo();
        
;
 
Factory * FactoryMethod(enum phoneType type) 
    switch(type) 
        case miType:
            return  new  miFactory();
        case huaweiType:
            return new  huaweiFactory();
        case oppoType:
            return new  oppoFactory();
        case vivoType:
            return new  vivoFactory();
        default:
            return NULL;
       

 
int main() 
    
    Factory *f;
    f =FactoryMethod(miType);
    f->createPhone()->show();
    delete f;
    f =FactoryMethod(huaweiType);
    f->createPhone()->show();
    delete f;
    f =FactoryMethod(oppoType);
    f->createPhone()->show();
    delete f;
    f =FactoryMethod(vivoType);
    f->createPhone()->show();
    delete f;
    f = NULL;
    return 0;

这时候这家公司赚了大钱,手机市场已经无人能敌,开始不满足于专门干手机了,开始玩起电脑来了,那么按照工厂方法模式来干的话就是哐哐一顿建工厂,好了又建了4个造电脑的工厂,突然有一天,老板发现造小米手机和小米电脑好多工序都是一样的,设备可以共享,只要在原来的造小米手机的工厂稍微改装一下,就能造电脑了,此时老板是气的跳脚啊,浪费了这么多资源,于是抽象工厂应运而生。

抽象工厂模式

AbstractFactory模式和Factory模式的区别是初学设计模式时候的一个经常容易引起困惑的地方,都有了工厂方法模式了,还要抽象工厂工厂模式干嘛?
我直接加工厂接口不就可以了,实际上,AbstractFactory模式是为创建一组(有多类)相关或依赖的对象提供创建接口,而Factory模式是为一类对象提供创建接口的。
好处就是:用抽象工厂模式可以避免创建很多不必要的Factory类。

**#include <iostream>
using namespace std; 
 
enum phoneType 
    miType = 0,
    huaweiType,
    oppoType,
    vivoType
;
 
class phone 
    public:
        virtual void show()=0; 
; 
 
class mi:public phone
    public:   
        void show() 
            cout<<"mi phone create"<<endl;
        
;
 
class huawei: public phone 
    public:
        void show() 
            cout<<"huawei phone create"<<endl;
        
;
 
class oppo: public phone 
    public:
        void show() 
            cout<<"oppo phone create"<<endl;
        
;
 
class vivo: public phone 
    public:
        void show() 
            cout<<"vivo phone create"<<endl;
        
;
 
class computer 
     public:
        virtual void show()=0;
;
 
class mi_computer:public computer
    public:   
        void show() 
            cout<<"mi computer create"<<endl;
        
;
 
class huawei_computer: public computer 
    public:
        void show() 
            cout<<"huawei computer create"<<endl;
        
;
 
class oppo_computer: public computer 
    public:
        void show() 
            cout<<"oppo computer create"<<endl;
        
;
 
class vivo_computer: public computer 
    public:
        void show() 
            cout<<"vivo computer create"<<endl;
        
;
 
class Factory 
    public:
       virtual  phone* createPhone()  = 0;
       virtual  computer* createComputer()  = 0;
;
 
class miFactory:public Factory 
    public:
        phone* createPhone() 
            return new mi();
        
        computer* createComputer() 
            return new mi_computer();
        
;
 
class huaweiFactory:public Factory 
    public:
        phone* createPhone() 
            return new huawei();
        
        computer* createComputer() 
            return new huawei_computer();
        
;
 
class oppoFactory:public Factory 
    public:
        phone* createPhone() 
            return new oppo();
        
        computer* createComputer() 
            return new oppo_computer();
        
;
 
class vivoFactory:public Factory 
    public:
        phone* createPhone() 
            return new vivo();
        
        computer* createComputer() 
            return new vivo_computer();
        
;
 
Factory * FactoryMethod(enum phoneType type) 
    switch(type) 
        case miType:
            return  new  miFactory();
        case huaweiType:
            return new  huaweiFactory();
        case oppoType:
            return new  oppoFactory();
        case vivoType:
            return new  vivoFactory();
        default:
            return NULL;
       

 
int main() 
    
    Factory *f;
    f =FactoryMethod(miType);
    f->createPhone()->show();
    f->createComputer()->show();
    delete f;
    f =FactoryMethod(huaweiType);
    f->createPhone()->show();
    f->createComputer()->show();
    delete f;
    f =FactoryMethod(oppoType);
    f->createPhone()->show();
    f->createComputer()->show();
    delete f;
    f =FactoryMethod(vivoType);
    f->createPhone()->show();
    f->createComputer()->show();
    delete f;
    f = NULL;
    return 0;
**

参考资料

C++实现设计模式——工厂模式

设计模式实践笔记第二节:抽象工厂模式(代码片段)

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式(AbstractFactory)也是一种创建型设计模式,通常用来解决「产品族」的创建问题。抽象工厂模式结构工厂模... 查看详情

设计模式实践笔记第二节:抽象工厂模式(代码片段)

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式(AbstractFactory)也是一种创建型设计模式,通常用来解决「产品族」的创建问题。抽象工厂模式结构工厂模... 查看详情

设计模式实践笔记第二节:抽象工厂模式(代码片段)

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式(AbstractFactory)也是一种创建型设计模式,通常用来解决「产品族」的创建问题。抽象工厂模式结构工厂模... 查看详情

设计模式c++工厂方法模式(代码片段)

推荐阅读设计模式C++简单工厂模式工厂方法模式是在简单工厂模式的缺点上进行优化的,我们都知道,在简单工厂模式中,要去增加或者减少一个产品的类型,都需要修改工厂中的if-else判断。这样子显然不... 查看详情

策略模式与工厂模式实践(代码片段)

hello,大家好,我是聪聪。文章目录1.介绍2.策略模式结构2.1分支逻辑解释2.2策略模式设计2.3策略模式代码2.3.1通用策略接口及其各策略实现。2.3.2执行上下文信息2.3.3客户端调用2.3.4总结3.常用示例3.1定义一个策略枚举3.2策... 查看详情

策略模式与工厂模式实践(代码片段)

hello,大家好,我是聪聪。文章目录1.介绍2.策略模式结构2.1分支逻辑解释2.2策略模式设计2.3策略模式代码2.3.1通用策略接口及其各策略实现。2.3.2执行上下文信息2.3.3客户端调用2.3.4总结3.常用示例3.1定义一个策略枚举3.2策... 查看详情

策略模式与工厂模式实践(代码片段)

hello,大家好,我是聪聪。文章目录1.介绍2.策略模式结构2.1分支逻辑解释2.2策略模式设计2.3策略模式代码2.3.1通用策略接口及其各策略实现。2.3.2执行上下文信息2.3.3客户端调用2.3.4总结3.常用示例3.1定义一个策略枚举3.2策... 查看详情

设计模式之工厂模式c++实现(代码片段)

参考书籍《HeadFirst设计模式》参考文章:设计模式:简单工厂、工厂方法、抽象工厂之小结与区别_superbeck的专栏-CSDN博客_简单工厂模式,工厂方法模式,抽象工厂模式简单工厂,工厂方法,抽象工厂都属于设计模式... 查看详情

设计模式之工厂模式c++实现(代码片段)

参考书籍《HeadFirst设计模式》参考文章:设计模式:简单工厂、工厂方法、抽象工厂之小结与区别_superbeck的专栏-CSDN博客_简单工厂模式,工厂方法模式,抽象工厂模式简单工厂,工厂方法,抽象工厂都属于设计模式... 查看详情

工厂模式c++实现(代码片段)

参考书籍《HeadFirst设计模式》参考文章:设计模式:简单工厂、工厂方法、抽象工厂之小结与区别_superbeck的专栏-CSDN博客_简单工厂模式,工厂方法模式,抽象工厂模式简单工厂,工厂方法,抽象工厂都属于设计模式... 查看详情

c++工厂模式(代码片段)

...(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。这里很容易出现的一个问题n多的子类继承自抽... 查看详情

软件工程第二次实践(代码片段)

实现一个能够对文本文件中的单词的词频进行统计的控制台程序1.Github项目地址:xinz2.PSP表格3.解题思路描述:拿到题目之后,先总的浏览了两遍,大致上明白了题意和需要用的知识。首先得先通过学习学会如何使用c++读取和写... 查看详情

(c++设计模式)——常见设计模式学习笔记-factory模式(工厂)(代码片段)

...我们开发的过程中,有时候需要用到一些只需要定义接口,然后让子类去决定实例化哪个类的情况,就可以用到我们所说的工厂方法(FactoryMethod)来解决这个问题,那 查看详情

num08---工厂方法模式(代码片段)

...的逻辑判断的代码。工厂模式解决了这个缺点。将工厂类接口抽象化,然后创建不同的子类工厂类,实现工厂类接口。每个子类工厂去实现具体的逻辑产品类。本质上就是把原有工厂类实现的实例化代码逻辑 延迟 到其子... 查看详情

java设计模型解析工厂模式proxy-agent模式templete模式(代码片段)

...yDesignpattern工厂设计模式的优点(1)工厂设计模式提供了接口而不是实现的代码方法。(2)工厂模式从客户端代码中删除实际实现类的实例化。工厂模式使我们的代码更健壮,耦合更少,易于扩展。例如,我们可以轻松更改PC类... 查看详情

c++提高工厂模式(代码片段)

...定应该创建哪一类产品类(这些产品类继承自一个父类或接口)的实例 查看详情

策略模式与工厂模式实践(代码片段)

hello,大家好,我是聪聪。文章目录1.介绍2.策略模式结构2.1分支逻辑解释2.2策略模式设计2.3策略模式代码2.3.1通用策略接口及其各策略实现。2.3.2执行上下文信息2.3.3客户端调用2.3.4总结3.常用示例3.1定义一个策略枚举3.2策... 查看详情

三种工厂模式的c++实现(代码片段)

...(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。这里很容易出现的一个问题n多的子类继承自抽... 查看详情