• 设计模式之工厂模式


    一、问题的提出

    现假设需要生产两种产品或创建两个对象,我们一般的方法如下代码所示:

    //protoProduct.h
    class ProductA
    {
    public:
        virtual void operation();
    };
    class ProductB
    {
    public:
        virtual void operation();
    };
    
    //protoProduct.cpp
    #include <iostream>
    #include "protoProduct.h"
    void ProductA::operation()
    {
        std::cout<<"create productA"<<std::endl;
        
    }
    
    void ProductB::operation()
    {
        std::cout<<"create productB"<<std::endl;
        
    }
    
    //main.cpp
    #include "protoProduct.h"
    void main()
    {
    
        ProductA *pa=new ProductA();
        pa->operation();
    
        ProductB *pb=new ProductB();
        pb->operation();
        
        delete pa;
        delete pb;
        pa=NULL;
        pb=NULL;
            return ;
    }
    View Code

    在此,我们为每个产品定义了一个类,客户端(main)在使用的时候,通过new操作符逐个创建对象,即客户端每次使用不同的子类的时候都需要知道到底是用哪一个子类,当类比较少的时候还没什么问题,但是当类比较多的时候,管理起来就非常的麻烦了,就必须要做大量的替换。而工厂模式主要的目的是为了实例化对象,用工厂方法代替new操作,从而封装对对象的操作。

    二、简单工厂模式

    //SimpleFactory.h
    class AbstractProduct
    {
    public:
        virtual void operation()=0;
    };
    
    class ProductA:public AbstractProduct
    {
    public:
        virtual void operation();
    };
    
    class ProductB:public AbstractProduct
    {
    
    public:
        virtual void operation();
    };
    
    class AbstractFactory
    {
    public:
        virtual AbstractProduct* creatProduct(char type)=0;
    
    };
    class SimpleFactory:public AbstractFactory
    {
    public:
        virtual AbstractProduct* creatProduct(char type);
    };
    
    //SimpleFactory.cpp
    #include <iostream>
    #include "SimpleFactory.h"
    
    void ProductA::operation()
    {
        std::cout<<"create the productA"<<std::endl;
    }
    
    void ProductB::operation()
    {
        std::cout<<"create the productB"<<std::endl;
    }
    
    AbstractProduct* SimpleFactory::creatProduct(char type)
    {
        AbstractProduct *temp=NULL;
        switch(type)
        {
        case 'A':
            temp=new ProductA();
            break;
        case 'B':
            temp=new ProductB();
            break;
        default:
            break;
        }
        return temp;
    }
    //main.cpp
    #include "SimpleFactory.h"
    void main()
    {
            AbstractFactory *factory=new SimpleFactory();
        AbstractProduct *pruduct=factory->creatProduct('A');
        pruduct->operation();
    
        pruduct=factory->creatProduct('B');
        pruduct->operation();
            delete pruduct;
        delete factory
            pruduct=NULL;
        factory=NULL;    
    
            return;
    }
    View Code

    简单工厂模式是工厂模式中最简单的一种,他可以用比较简单的方式隐藏创建对象的细节,一般只需要告诉工厂类所需要的类型,工厂类就会返回需要的产品类,但客户端看到的只是产品的抽象对象,无需关心到底是返回了哪个子类。客户端唯一需要知道的具体子类就是工厂子类。除了这点,基本是达到了依赖倒转原则的要求。

    如果我每次用简单工厂类创建的类型都不相同,这样修改起来的时候还是会出现问题,还是需要大量的替换。所以简单工厂模式一般应该于程序中大部分地方都只使用其中一种产品,工厂类也不用频繁创建产品类的情况。这样修改的时候只需要修改有限的几个地方即可。

    适用场合

    1. 在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式;
    2. 由于对象的创建过程是我们不需要去关心的,而我们注重的是对象的实际操作,所以,我们需要分离对象的创建和操作两部分,如此,方便后期的程序扩展和维护。

    三、工厂模式

    目的:

    Define an interface for creating an object, but let subclasses decide which class  to instantiate. Factory Method lets a class defer instantiation to subclasses.

    定义一个用于创建对象的接口,让子类决定实例化哪一个类。

    //Factory.h
    class AbstractProduct
    {
    public:
        virtual void operation()=0;
    };
    
    class ProductA:public AbstractProduct
    {
    public:
        virtual void operation();
    };
    
    class ProductB:public AbstractProduct
    {
        
    public:
        virtual void operation();
    };
    
    class AbstractFactory
    {
    public:
        virtual AbstractProduct* createProduct()=0;
        
    };
    class SimpleFactoryA:public AbstractFactory
    {
    public:
        virtual AbstractProduct* createProduct();
    };
    class SimpleFactoryB:public AbstractFactory
    {
    public:
        virtual AbstractProduct* createProduct();
    };
    
    //Factory.cpp
    #include <iostream>
    #include "Factory.h"
    
    void ProductA::operation()
    {
        std::cout<<"create the productA"<<std::endl;
    }
    
    void ProductB::operation()
    {
        std::cout<<"create the productB"<<std::endl;
    }
    
    AbstractProduct* SimpleFactoryA::createProduct()
    {
        AbstractProduct *temp=NULL;
        temp=new ProductA();
        return temp;
    }
    
    AbstractProduct* SimpleFactoryB::createProduct()
    {
        AbstractProduct *temp=NULL;
        temp=new ProductB();
        return temp;
    }
    //main.cpp
    #include "Factory.h"
    void main()
    {
        
        AbstractFactory *factory=new SimpleFactoryA();
        AbstractProduct *product=factory->createProduct();
        product->operation();
    
        delete factory;
        factory=NULL;
        factory=new SimpleFactoryB();
        product=factory->createProduct();
        product->operation();
        delete product;
        delete factory;
        product=NULL;
        factory=NULL;
        return;
    }       
    View Code

    工厂模式基本与简单工厂模式差不多,上面也说了,每次添加一个产品子类都必须在工厂类中添加一个判断分支,这样违背了开放-封闭原则,因此,工厂模式就是为了解决这个问题而产生的。

    既然每次都要判断,那我就把这些判断都生成一个工厂子类,这样,每次添加产品子类的时候,只需再添加一个工厂子类就可以了。这样就完美的遵循了开放-封闭原则。但这其实也有问题,如果产品数量足够多,要维护的量就会增加,好在一般工厂子类只用来生成产品类,只要产品子类的名称不发生变化,那么基本工厂子类就不需要修改,每次只需要修改产品子类就可以了。

    同样工厂模式一般应该于程序中大部分地方都只使用其中一种产品,工厂类也不用频繁创建产品类的情况。这样修改的时候只需要修改有限的几个地方即可。

    适用场合

    工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

    1. 在设计的初期,就考虑到产品在后期会进行扩展的情况下,可以使用工厂方法模式;
    2. 产品结构较复杂的情况下,可以使用工厂方法模式;

    四、抽象工厂模式

    目的:

    Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    //AbstractFactory.h
    class AbstractProductA
    {
    public:
        virtual void operation()=0;
        virtual void fly()=0;
    };
    
    class AbstractProductB
    {
        
    public:
        virtual void operation()=0;
        virtual void swim()=0;
    };
    
    class ProductA1:public AbstractProductA
    
    {
    public:
        virtual void operation();
        virtual void fly();
    protected:
    private:
    };
    
    class ProductA2:public AbstractProductA
    {
    public:
        virtual void operation();
        virtual void fly();
    };
    
    class ProductB1:public AbstractProductB
    {
    public:
        virtual void operation();
        virtual void swim();
        
    };
    
    class ProductB2:public AbstractProductB
    {
    public:
        virtual void operation();
        virtual void swim();
        
    };
    
    class AbstractFactory
    {
    public:
        virtual AbstractProductA* createProductA()=0;
        virtual AbstractProductB* createProductB()=0;
        
    };
    class SimpleFactory1:public AbstractFactory
    {
    public:
        virtual AbstractProductA* createProductA();
        virtual AbstractProductB* createProductB();
    };
    class SimpleFactory2:public AbstractFactory
    {
    public:
        virtual AbstractProductA* createProductA();
        virtual AbstractProductB* createProductB();
    };
    //AbstractFactory.cpp
    #include <iostream>
    #include "AbstractFactory.h"
    /*
    void AbstractProductA::operation()
    {
        std::cout<<"create the productA"<<std::endl;
    }
    
    void AbstractProductB::operation()
    {
        std::cout<<"create the productB"<<std::endl;
    }
    */
    void ProductA1::operation()
    {
        std::cout<<"create the productA1"<<std::endl;
    }
    void ProductA1::fly()
    {
        std::cout<<"productA1 can  fly slowly"<<std::endl;
    }
    
    void ProductA2::operation()
    {
        std::cout<<"create the productA2"<<std::endl;
    }
    
    void ProductA2::fly()
    {
        std::cout<<"productA1 can fly quickly"<<std::endl;
    }
    
    void ProductB1::operation()
    {
        std::cout<<"create the productB1"<<std::endl;
    }
    void ProductB1::swim()
    {
        std::cout<<"productB1 can swim slowly"<<std::endl;
    }
    void ProductB2::operation()
    {
        std::cout<<"create the productB2"<<std::endl;
    }
    void ProductB2::swim()
    {
        std::cout<<"productB1 can swim quickly"<<std::endl;
    }
    
    
    AbstractProductA* SimpleFactory1::createProductA()
    {
        AbstractProductA *temp=NULL;
        temp=new ProductA1();
        return temp;
    }
    
    AbstractProductB* SimpleFactory1::createProductB()
    {
        AbstractProductB *temp=NULL;
        temp=new ProductB1();
        return temp;
    }
    
    AbstractProductA* SimpleFactory2::createProductA()
    {
        AbstractProductA *temp=NULL;
        temp=new ProductA2();
        return temp;
    }
    
    AbstractProductB* SimpleFactory2::createProductB()
    {
        AbstractProductB *temp=NULL;
        temp=new ProductB2();
        return temp;
    }
    
    //main.cpp
    
    void main()
    {
        AbstractFactory* factory = new SimpleFactory1();
        AbstractProductA* productA = factory->createProductA();
        AbstractProductB* productB = factory->createProductB();
        productA->operation();
        productA->fly();
        productB->operation();
        productB->swim();
        
        delete factory;
        factory = NULL;
        delete productA;
        productA = NULL;
        delete productB;
        productB = NULL;
        
        factory = new SimpleFactory2();
        productA = factory->createProductA();
        productB = factory->createProductB();
        productA->operation();
        productA->fly();
        productB->operation();
        productB->swim();
        
        delete factory;
        factory = NULL;
        delete productA;
        productA = NULL;
        delete productB;
        productB = NULL;
    
    
        return;
    
    }
    View Code

    抽象工厂模式就变得比工厂模式更为复杂,就像上面提到的缺点一样,工厂模式和简单工厂模式要求产品子类必须要是同一类型的,拥有共同的方法,这就限制了产品子类的扩展。于是为了更加方便的扩展,抽象工厂模式就将同一类的产品子类归为一类,让他们继承同一个抽象子类,我们可以把他们一起视作一组,然后好几组产品构成一族。

    适用场合

    工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,主要用于创建一组(有多个种类)相关的产品,为它们提供创建的接口;就是当具有多个抽象角色时,抽象工厂便可以派上用场。

    五、总结

    六、参考

    1 三种工厂模式的分析以及C++实现

    2 C++设计模式--简单工厂模式

    3 设计模式C++实现(1)--工厂模式

    4 Factory method pattern

    5 Abstract Factory pattern

  • 相关阅读:
    2007417 13:01:00 运行时数据结构
    2008515 1:38:00 为受灾的人们祈福,祭那些在地震中离开的人
    200732 19:00:00 一段设置8253芯片的程序
    从实模式到保护模式
    200739 18:01:00 linux界的元老
    2007311 19:11:00 cpu执行第一条指令时情形
    20061127 19:54:00 在你心中有这样的一个人吗? (转)
    linux0.11内存管理——try_to_share()
    2007413 20:46:00 linux0.11之copy_page_tables()函数见解
    POJ1258AgriNet
  • 原文地址:https://www.cnblogs.com/gjianw217/p/3864174.html
Copyright © 2020-2023  润新知