工程实践之路:C++接口设计中的工厂模型

Posted CodeBowl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工程实践之路:C++接口设计中的工厂模型相关的知识,希望对你有一定的参考价值。


上一篇文章写了 《工程实践: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++实现设计模式——工厂模式

以上是关于工程实践之路:C++接口设计中的工厂模型的主要内容,如果未能解决你的问题,请参考以下文章

设计模式在外卖营销业务中的实践

设计模式在美团外卖营销业务中的实践

设计模式在美团外卖营销业务中的实践

AoE工程实践 —— 记CoreML模型在CocoaPods应用中的集成(上)

一起来学设计模式-----工厂模式的实践

WEBAPI实践之路