• 设计模式之简单工厂模式


    2018-09-16 23:50:57

    简单工厂模式概述

      简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。  

      UML类图如下:

      

      该模式中包含的角色及其职责(摘自 :百度百科
      工厂(Creator)角色
      简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
      抽象产品(Product)角色
      简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
      具体产品(Concrete Product)角色
      是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

       优点:

      产品的者只需要消费工厂的使用者,而不用关心这些类是如何组织的,如何创建的。所以工厂类是整个模式的核心。简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对客户端来说去除了与具体产品的依赖。

      缺点:

      优于类对象的全部创建逻辑集中在了同一个类里,所以它只能适用于已经考虑好的类。如果有新的类要加入,那么必须要修改工厂类,这违背了开闭原则。

      应用场景:

      客户知道传入工厂类的参数,使用工厂类的产品。适用于工厂创建的实例比较少的情况。

    知识储备

      简单工厂模式是利用继承来实现的(继承里的虚函数、纯虚函数的底层实现,在其它部分写学习体会)。C++里没有接口的概念,但是可以使用虚基类来模仿接口,虚基类的作用就是告诉它的继承者有哪些接口你必须要实现,那么什么叫虚基类了,包含有形如:virtual retType functionName() = 0(这就是纯虚函数);的声明的类就叫做虚基类,如果方法被这样声明,那么意味着它的继承者必须要实现virtual retType functionName() 这个方法。当然也可以声明:virtual retType functionName(){}(虚函数)这样的方法,它不是必须要在子类中实现的。另外,注意析构函数必须是virtual的,这是为了在销毁对象时能正确的知道应该调用哪个类的析构函数。我这里说的虚基类就是在概述中提到的工厂,虚基类的子类就是流水线。那么同样的在生产产品时,为了实现产品的产品族形式生产,那么产品也该有这样一个继承体系。

    代码实现

    产品类的虚基类:

    #ifndef ABSTRACTPRODUCT_H_
    #define ABSTRACTPRODUCT_H_
    #include <string>
    class AbstractProduct
    {
    public:
        virtual void setName(const std::string &strName) =0;
        virtual const std::string& getName() const =0;
        AbstractProduct() = default;
        virtual ~AbstractProduct() = default;
    };
    #endif
    AbstractProduct.h

    两个示例产品

    #ifndef PRODUCTA_H_
    #define PRODUCTA_H_
    #include "AbstractProduct.h"
    class ProductA : public AbstractProduct
    {
    private:
        std::string m_strName;
    public:
        void setName(const std::string &strName)
        {
        m_strName = strName;
        }
        const std::string& getName() const
        {
        return m_strName;
        }
        ProductA() = default;
        ~ProductA() = default;
    };
    #endif
    ProductA.h
    #ifndef PRODUCTB_H_
    #define PRODUCTB_H_
    #include "AbstractProduct.h"
    class ProductB : public AbstractProduct
    {
    private:
       std::string m_strName;
    public:
       void setName(const std::string &strName)
       {
        m_strName = strName;
       }
       const std::string& getName() const
       {
        return m_strName;
       }
       ProductB() = default;
       ~ProductB() = default;
    };
    #endif
    ProductB.h

    工厂类示例:

    #ifndef SIMPLEFACTORT_H_
    #define SIMPLEFACTORY_H_
    enum ProductType
    {
        A,
        B
    };
    #include "AbstractProduct.h"
    #include "ProductA.h"
    #include "ProductB.h"
    class SimpleFactory
    {
    public:
        AbstractProduct* createProduct(const int Type);
        SimpleFactory() = default;
        ~SimpleFactory() = default;
    };
    #endif
    SimpleFactory.h
    #include "SimpleFactory.h"
    
    AbstractProduct* SimpleFactory::createProduct(const int iType)
    {
       AbstractProduct* retObj = nullptr;
       switch(iType)
       {
        case ProductType::A:
        {
             retObj = new ProductA();
        }
        break;
        case ProductType::B:
        {
             retObj = new ProductB();
        }
        break;
        default:
        break;
       }
       return retObj;
    }
    SimpleFactory.cpp

    主函数:

    #include "SimpleFactory.h"
    #include <iostream>
    using namespace std;
    
    int main(int argc,char *argv[])
    {
       SimpleFactory objSimpleFactory;
       auto objRet1 = objSimpleFactory.createProduct(0);
       std::string strName1 = "Name";
       objRet1->setName(strName1);
       std::cout << "Product : " << objRet1->getName() <<std::endl;
       auto objRet2 = objSimpleFactory.createProduct(1);
       std::string strNameB = "ProductB";
       objRet2->setName(strNameB);
       std::cout << "Product B: " << objRet2->getName() << std::endl;
       if(nullptr != objRet1)
       {
        delete objRet1;
        objRet1 = nullptr;
       }
       if(nullptr != objRet2)
       {
        delete objRet2;
        objRet2 = nullptr;
       }
       return(1);
    }
    main.cpp
  • 相关阅读:
    简单的一个php验证登陆代码
    目标,信念,坚强,淡定,团队
    linux下安装redis及PHP扩展应用
    mysql 命令行 隔离级别
    数据库事务的隔离级别
    mysql 乐观锁和悲观锁
    SpringBoot跨域问题CORS解决
    Oracle SQL题目及其解答(学生、课程、成绩、教师)
    SpringCloud学习2-eureka
    SpringCloud学习1-概述
  • 原文地址:https://www.cnblogs.com/ToBeExpert/p/9658529.html
Copyright © 2020-2023  润新知