• 设计模式之工厂模式


    2018-09-18 01:35:36

    工厂模式概述

      在简单工厂模式中,我们讲过简单工厂模式的一个缺点就是在扩展时会违背开闭原则。工厂模式就是针对简单工厂模式扩展性上的一种改进。工厂模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使的实例化延迟到了其子类(其实就是在简单工厂模式的UML图中在生产端形成了类似产品端的继承体系)。客户在使用时需要知道它的产品是由哪一个工厂生产的。

      工厂模式的实现,客户端需要决定示例化哪一个工厂来实例化对象,选择判断的问题还是存在的,也就是说,工厂方法把原来简单工厂模式的内部逻辑判断移到了客户端代码进行,你想要加功能,本来是修改工厂类,而现在是修改客户端。

    工厂模式UML图

      

    代码实现

      从整体结构上来说,工厂模式有4个大组件:1.工厂虚基类:抽象工厂,提供方法指导子类的行为;2.工厂虚基类的子类:实现其父类的接口,主要用于创建具体产品。3.产品虚基类:抽象产品,你可以视为这是一个产品的模具。它只能生产符合模具要求的产品;4.产品虚基类的子类:根据自己的情况实现其父类提供的接口。

            这里要注意一下,我们可以在使用子类指针的情况下使用其父类指针进行替代,但是前提是,父类和子类必须要具有相同的类声明。(运行时多态)

    1.抽象工厂类:

    #ifndef ABSTRACTFACTORY_H_
    #define ABSTRACTFACTORY_H_
    #include "AbstractProduct.h"
    class AbstractFactory
    {
    public:
        AbstractFactory() = default;
        virtual ~AbstractFactory() = default;
        virtual AbstractProduct* createProduct() = 0;
    };
    #endif
    AbstractFactory.h

    2.抽象产品类:

    #ifndef ABSTRACTPRODUCT_H_
    #define ABSTRACTPRODUCT_H_
    class AbstractProduct
    {
    public:
        int m_iLeftOper{0};
        int m_iRightOper{0};
        virtual const int getLeftOper() const =0;
        virtual const int getRightOper() const = 0;
        virtual void setLeftOper(const int iLeftOper) = 0;
        virtual void setRightOper(const int iRightOper) = 0;
        virtual int operate() const = 0;
        AbstractProduct() = default;
        virtual ~AbstractProduct() = default;
    };
    #endif
    AbstractProduct.h

    3.具体的产品类:

    #ifndef ADDOPERATION_H_
    #define ADDOPERATION_H_
    #include "AbstractProduct.h"
    class AddOperation:public AbstractProduct
    {
    public:
        const int getLeftOper() const override
        {
        return m_iLeftOper;
        }
        const int getRightOper() const override
        {
        return m_iRightOper;
        }
        void setLeftOper(const int iLeftOper) override
        {
        m_iLeftOper = iLeftOper;
        }
        void setRightOper(const int iRightOper) override
        {
        m_iRightOper = iRightOper;
        }
        int operate() const override
        {
        return m_iRightOper + m_iLeftOper;
        } 
    };
    #endif
    AddOperation.h

            显然,在我们第一个版本的时候只有一个产品需要使用,这个产品就是AddOperation,要想使用这个产品我们必须要实现一个具体的工厂类,专门用于生产这一类型的实例:

    4.具体的工厂类:

     AddOperationFactory.h

    #include "AddOperationFactory.h"
    
    AbstractProduct* AddOperationFactory::createProduct()
    {
        return new AddOperation();
    }
    AddOperationFactory.cpp

    5.客户端对这个工厂类的使用:

    #include "AddOperationFactory.h"
    #include "AbstractFactory.h"
    #include <iostream>
    
    using namespace std;
    int main(int argc,char *argv[])
    {
        AbstractFactory *objAbstractFactory = new AddOperationFactory(); 
        auto objAdd = objAbstractFactory->createProduct();
        objAdd->setLeftOper(1);
        objAdd->setRightOper(2);
        cout << objAdd->operate() << endl;
        cout << "LeftOper is "<< objAdd->getLeftOper() << endl;
        cout << "RightOper is " << objAdd->getRightOper() << endl; 
        if(nullptr != objAbstractFactory)
        {
        delete objAbstractFactory;
        objAbstractFactory = nullptr;
        }
        if(nullptr != objAdd)
        {
        delete objAdd;
        objAdd = nullptr;
        }
        return(1);
    }
    main.cpp

      我这个示例就是一个简单的四则运算,第一次只支持加法运算,假设第二个版本的时候,老板让加一个减法运算,那么这个时候我需要做三件事情,一个是由AbstractProduct类派生出一个减法类,第二个事情是由AbstractFactory类派生出一个用于产生减法类实例的减法工厂。第三个事情,假设减法类,叫做SubOperation,减法工厂叫做SubOperationFactory。在客户端使用这个工厂的时候,我们要使用SubOperationFactory类来生产SubOperation的实例。就是说客户端将会出现如下代码:

    #include "AddOperationFactory.h"
    #include "AbstractFactory.h"
    #include "SubOperationFactory.h"
    #include "SubOperation.h"
    #include <iostream>
    
    using namespace std;
    int main(int argc,char *argv[])
    {
        AbstractFactory *objAbstractFactory = new AddOperationFactory();
        auto objAdd = objAbstractFactory->createProduct();
        objAdd->setLeftOper(1);
        objAdd->setRightOper(2);
        cout << objAdd->operate() << endl;
        cout << "LeftOper is "<< objAdd->getLeftOper() << endl;
        cout << "RightOper is " << objAdd->getRightOper() << endl; 
        if(nullptr != objAbstractFactory)
        {
        delete objAbstractFactory;
        objAbstractFactory = nullptr;
        }
        if(nullptr != objAdd)
        {
        delete objAdd;
        objAdd = nullptr;
        }
        AbstractFactory *objSubFactory = new SubOperationFactory();
        AbstractProduct *objSubOperation = objSubFactory->createProduct();
         objSubOperation->setLeftOper(3);
         objSubOperation->setRightOper(1);
         std::cout << objSubOperation->operate() << end;
        if(nullptr != objSubFactory)
        {
              delete objSubFactory;
              objSubFactory = nullptr;
        }
        if(nullptr != objSubOperation)
        {
              delete objSubOperation;
              objSubOperation = nullptr;
         }
        return(1);
    }
    程序第二版的扩展

      工厂模式和简单工厂模式都是集中分装了对象的创建,使得更换对象时,不需要做太大的改动即可实现,降低了客户程序与产品的耦合度。工厂模式是简单工厂模式的进一步抽象和推广,它克服了简单工厂模式带来的违法开放-封闭原则的缺点,但是自己的缺点是,没增加一个新的产品,就要加一个产品工厂的类,增加了额外的开发量。另外在生产具体的产品时,客户端必须要知道它需要的产品将由哪个类(工厂)生产。

    第一次学习设计模式,欢迎指正。

  • 相关阅读:
    Selenium IDE的第一个测试用例——路漫长。。。
    selenium学习第三天,新建一个测试用例(运行失败)。
    Selenium学习第二天,了解Selenium工作模式与学习Selenium需要具备的知识与工具。
    了解Selenium与自动化测试第一天“云里雾里”
    javascript冷知识
    HTTP权威指南学习心得
    (六)Linux进程调度-实时调度器_学习笔记
    (五)Linux进程调度-CFS调度器_学习笔记
    (四)Linux进程调度-组调度及带宽控制_学习笔记
    (三)Linux进程调度器-进程切换_学习笔记
  • 原文地址:https://www.cnblogs.com/ToBeExpert/p/9665988.html
Copyright © 2020-2023  润新知