现在的位置: 首页 > 综合 > 正文

C++设计模式之Factory(工厂)模式

2018年04月13日 ⁄ 综合 ⁄ 共 11456字 ⁄ 字号 评论关闭

工厂模式一般是学习设计模式的第一课,它本身也是创建型模式中较为常用的一种模式.

工厂模式希望解决的是"如何高效而方便的创建当前需要的对象"的问题.当一个对象对外提供的接口稳定,而这类对象的具体实现容易发生变化时,我们可以考虑使用工厂来封装对象的实现变化,并提供统一的对象创建方法.

工厂模式可以分为三种不同的模式,分别对应不同情况下的解决方案.


  • 1.简单工厂模式

简单工厂通过一个工厂类对象创建出所有的产品类.通过外部给予的条件参数,动态的创建出不同的产品类的实例.类图如下:

示例代码:

// 产品接口类
class IProduct abstract
{
public:
    virtual ~IProduct()
    {
    }
 
public:
    virtual void Func() = 0;
};
 
// 具体的产品类
 
class CAProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product A") << endl;
    }
};
 
class CBProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product B") << endl;
    }
};
 
class CCProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product C") << endl;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 简单工厂类
class CSimpleFactory
{
public:
    static TSmartPtr<IProduct> CreateProduct(const _tstring& str)
    {
        if( str == _T("A") )
            return new CAProduct;
        else if( str == _T("B") )
            return new CBProduct;
        else if( str == _T("C") )
            return new CCProduct;
        else
            return NULL;
    }
};

调用方式:

_tcout << _T("简单工厂:") << endl;
// 利用简单工厂创建产品
CSimpleFactory::CreateProduct(_T("A"))->Func();        // 创建产品A并调用
CSimpleFactory::CreateProduct(_T("B"))->Func();        // 创建产品B并调用
CSimpleFactory::CreateProduct(_T("C"))->Func();        // 创建产品C并调用

简单工厂在所有工厂模式中实现上最为简便,而且并不需要很多的工厂类,同时很好的将产品类的创建过程封装,并解耦产品类实现与调用.

它最大的硬伤在于工厂类内部包含了所有具体产品类的构建.当我们需要增加某个产品类,或者修改某个产品类的构建方式时,我们就不得不修改工厂类.

下面的工厂方法模式可以解决这个问题.


  • 2.工厂方法模式

工厂方法模式通过一个工厂接口定义多个工厂类对象,将创建具体产品类的工作推迟到单独的工厂子类当中,从而将具体的产品类创建过程与工厂类对象解耦.类图如下:

示例代码:

// 工厂接口类
class IFactory abstract
{
public:
    virtual TSmartPtr<IProduct> CreateProduct() = 0;
};
 
// 具体的工厂类
 
class CAFactory : public IFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CAProduct;
    }
};
 
class CBFactory : public IFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CBProduct;
    }
};
 
class CCFactory : public IFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CCProduct;
    }
};

调用方式:

_tcout << _T("工厂方法:") << endl;
TSmartPtr<IFactory> c_p_factory;
// 利用工厂方法创建产品
c_p_factory = new CAFactory;
c_p_factory->CreateProduct()->Func();            // 创建产品A并调用
c_p_factory = new CBFactory;
c_p_factory->CreateProduct()->Func();            // 创建产品B并调用
c_p_factory = new CCFactory;
c_p_factory->CreateProduct()->Func();            // 创建产品C并调用

可以看到,此时当我们需要增加一个新的产品时,只需要增加一个对应的工厂类即可,不需要修改原来的任何代码.


  • 3.抽象工厂模式

从上面的叙述中,我们似乎感觉问题已经比较完美的解决了,那么抽象工厂与工厂方法相比又优化了哪些地方呢?

工厂方法可以针对同一系列产品接口提供同一系列的工厂类,但是若我们有多个产品系列,每个系列的接口各不相同,此时我们就需要定义多个工厂类系列,颇为不方便.

抽象工厂将各个产品系列的接口统一到一个工厂系列中,通过一个工厂类对象可以创建出所有系列的对应产品.类图如下:


示例代码:

//////////////////////////////////////////////////////////////////
 
// 产品接口类
 
class IProduct abstract
{
public:
    virtual ~IProduct()
    {
    }
 
public:
    virtual void Func() = 0;
};
 
class IProduct2 abstract
{
public:
    virtual ~IProduct2()
    {
    }
 
public:
    virtual void Func2() = 0;
};
 
//////////////////////////////////////////////////////////////////
 
// 具体的产品类
 
class CAProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product A") << endl;
    }
};
 
class CBProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product B") << endl;
    }
};
 
class CCProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product C") << endl;
    }
};
 
// 具体的产品类2
 
class CAProduct2 : public IProduct2
{
public:
    virtual void Func2()
    {
        _tcout << _T("Product2 A") << endl;
    }
};
 
class CBProduct2 : public IProduct2
{
public:
    virtual void Func2()
    {
        _tcout << _T("Product2 B") << endl;
    }
};
 
class CCProduct2 : public IProduct2
{
public:
    virtual void Func2()
    {
        _tcout << _T("Product2 C") << endl;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 抽象工厂接口类
class IAbstractFactory abstract
{
public:
    virtual TSmartPtr<IProduct> CreateProduct() = 0;
    virtual TSmartPtr<IProduct2> CreateProduct2() = 0;
};
 
// 抽象工厂类
 
class CAFactory : public IAbstractFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CAProduct;
    }
 
    virtual TSmartPtr<IProduct2> CreateProduct2()
    {
        return new CAProduct2;
    }
};
 
class CBFactory : public IAbstractFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CBProduct;
    }
 
    virtual TSmartPtr<IProduct2> CreateProduct2()
    {
        return new CBProduct2;
    }
};
 
class CCFactory : public IAbstractFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CCProduct;
    }
 
    virtual TSmartPtr<IProduct2> CreateProduct2()
    {
        return new CCProduct2;
    }
};

调用方式:

_tcout << _T("抽象工厂:") << endl;
TSmartPtr<IAbstractFactory> c_p_factory;
// 利用抽象工厂创建产品
c_p_factory = new CAFactory;
c_p_factory->CreateProduct()->Func();                // 创建产品1A并调用
c_p_factory->CreateProduct2()->Func2();                // 创建产品2A并调用
c_p_factory = new CBFactory;
c_p_factory->CreateProduct()->Func();                // 创建产品1B并调用
c_p_factory->CreateProduct2()->Func2();                // 创建产品2B并调用
c_p_factory = new CCFactory;
c_p_factory->CreateProduct()->Func();                // 创建产品1C并调用
c_p_factory->CreateProduct2()->Func2();                // 创建产品2C并调用

我们可以看到,这种情况下如果我们采用工厂方法模式,肯定会出现大量的工厂类,让我们在使用中非常的头疼,维护起来也颇为麻烦.抽象工厂模式将同一种构建方法的不同产品族放入同一个工厂中处理,让调用者可以更加专注于定位自己需要的产品,而不是去判断各种令人眼花缭乱的工厂类.

在实际使用中,工厂方法和抽象工厂的使用都不是很多.原因是它们的工厂类都太多了,而且抽象工厂的外部接口逻辑也比较复杂.我们可以试试看用一个简单工厂来解决上面抽象工厂的问题:

// 简单工厂类
class CSimpleFactory
{
public:
    static TSmartPtr<IProduct> CreateProduct(const _tstring& str)
    {
        if( str == _T("A") )
            return new CAProduct;
        else if( str == _T("B") )
            return new CBProduct;
        else if( str == _T("C") )
            return new CCProduct;
        else
            return NULL;
    }
 
    static TSmartPtr<IProduct2> CreateProduct2(const _tstring& str)
    {
        if( str == _T("A") )
            return new CAProduct2;
        else if( str == _T("B") )
            return new CBProduct2;
        else if( str == _T("C") )
            return new CCProduct2;
        else
            return NULL;
    }
};
 
// ...
 
_tcout << _T("简单工厂:") << endl;
// 利用简单工厂创建产品
CSimpleFactory::CreateProduct(_T("A"))->Func();        // 创建产品1A并调用
CSimpleFactory::CreateProduct2(_T("A"))->Func2();    // 创建产品2A并调用
CSimpleFactory::CreateProduct(_T("B"))->Func();        // 创建产品1B并调用
CSimpleFactory::CreateProduct2(_T("B"))->Func2();    // 创建产品2B并调用
CSimpleFactory::CreateProduct(_T("C"))->Func();        // 创建产品1C并调用
CSimpleFactory::CreateProduct2(_T("C"))->Func2();    // 创建产品2C并调用

整个代码简洁明了,调用接口也很清晰.因此简单工厂是工厂模式中最为实用的一种了.唯一麻烦的地方就在于维护工厂内部逻辑上.往往为了达到通用的处理接口,工厂内部实现不会使用switch-case或者if-else,而采用RTTI或者类似的机制来完成类的动态创建.此时的工厂就是一个非常有力的武器,既有简单工厂的简洁清晰,又有抽象工厂添加改写的方便性.

运用好工厂模式,可以比较完美的解决多系列对象创建的需求变化,在使用之前必须将变化本身彻底封装入产品类,并提取出固定不变的通用接口.可以说,工厂模式彻底诠释了OOP面向接口编程的特征,融会贯通的用好了工厂模式,我们也就学会了如何将面向接口编程的思想代入到程序的其他需求实现中.


下面给出完整的示例代码:

  • Factory_Method.cpp
//////////////////////////////////////////////////////////////////
// 工厂方法模式 C++示例
//
// Author:    木头云
// Blog:    http://darkc.at
// E-Mail:    memleak@darkc.at
// Version:    1.0.819.1550(2009/08/19)
//////////////////////////////////////////////////////////////////
 
#include "stdafx.h"
 
//////////////////////////////////////////////////////////////////
 
// 产品接口类
class IProduct abstract
{
public:
    virtual ~IProduct()
    {
    }
 
public:
    virtual void Func() = 0;
};
 
// 具体的产品类
 
class CAProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product A") << endl;
    }
};
 
class CBProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product B") << endl;
    }
};
 
class CCProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product C") << endl;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 简单工厂类
class CSimpleFactory
{
public:
    static TSmartPtr<IProduct> CreateProduct(const _tstring& str)
    {
        if( str == _T("A") )
            return new CAProduct;
        else if( str == _T("B") )
            return new CBProduct;
        else if( str == _T("C") )
            return new CCProduct;
        else
            return NULL;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 工厂接口类
class IFactory abstract
{
public:
    virtual TSmartPtr<IProduct> CreateProduct() = 0;
};
 
// 具体的工厂类
 
class CAFactory : public IFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CAProduct;
    }
};
 
class CBFactory : public IFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CBProduct;
    }
};
 
class CCFactory : public IFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CCProduct;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 主函数
int _tmain(int argc, _TCHAR* argv[])
{
    _tcout << _T("简单工厂:") << endl;
    // 利用简单工厂创建产品
    CSimpleFactory::CreateProduct(_T("A"))->Func();        // 创建产品A并调用
    CSimpleFactory::CreateProduct(_T("B"))->Func();        // 创建产品B并调用
    CSimpleFactory::CreateProduct(_T("C"))->Func();        // 创建产品C并调用
 
    _tcout << _T("工厂方法:") << endl;
    TSmartPtr<IFactory> c_p_factory;
    // 利用工厂方法创建产品
    c_p_factory = new CAFactory;
    c_p_factory->CreateProduct()->Func();            // 创建产品A并调用
    c_p_factory = new CBFactory;
    c_p_factory->CreateProduct()->Func();            // 创建产品B并调用
    c_p_factory = new CCFactory;
    c_p_factory->CreateProduct()->Func();            // 创建产品C并调用
 
    return 0;
}
 
//////////////////////////////////////////////////////////////////
/*
    Factory Method要解决的就是对象的创建时机问题.
    它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,
    较好的解决了这种紧耦合的关系,很好地符合了开放封闭原则.
*/
//////////////////////////////////////////////////////////////////

  • Abstract_Factory.cpp

//////////////////////////////////////////////////////////////////
// 抽象工厂模式 C++示例
//
// Author:    木头云
// Blog:    http://darkc.at
// E-Mail:    memleak@darkc.at
// Version:    1.0.819.1540(2009/08/19)
//////////////////////////////////////////////////////////////////
 
#include "stdafx.h"
 
//////////////////////////////////////////////////////////////////
 
// 产品接口类
 
class IProduct abstract
{
public:
    virtual ~IProduct()
    {
    }
 
public:
    virtual void Func() = 0;
};
 
class IProduct2 abstract
{
public:
    virtual ~IProduct2()
    {
    }
 
public:
    virtual void Func2() = 0;
};
 
//////////////////////////////////////////////////////////////////
 
// 具体的产品类
 
class CAProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product A") << endl;
    }
};
 
class CBProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product B") << endl;
    }
};
 
class CCProduct : public IProduct
{
public:
    virtual void Func()
    {
        _tcout << _T("Product C") << endl;
    }
};
 
// 具体的产品类2
 
class CAProduct2 : public IProduct2
{
public:
    virtual void Func2()
    {
        _tcout << _T("Product2 A") << endl;
    }
};
 
class CBProduct2 : public IProduct2
{
public:
    virtual void Func2()
    {
        _tcout << _T("Product2 B") << endl;
    }
};
 
class CCProduct2 : public IProduct2
{
public:
    virtual void Func2()
    {
        _tcout << _T("Product2 C") << endl;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 简单工厂类
class CSimpleFactory
{
public:
    static TSmartPtr<IProduct> CreateProduct(const _tstring& str)
    {
        if( str == _T("A") )
            return new CAProduct;
        else if( str == _T("B") )
            return new CBProduct;
        else if( str == _T("C") )
            return new CCProduct;
        else
            return NULL;
    }
 
    static TSmartPtr<IProduct2> CreateProduct2(const _tstring& str)
    {
        if( str == _T("A") )
            return new CAProduct2;
        else if( str == _T("B") )
            return new CBProduct2;
        else if( str == _T("C") )
            return new CCProduct2;
        else
            return NULL;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 抽象工厂接口类
class IAbstractFactory abstract
{
public:
    virtual TSmartPtr<IProduct> CreateProduct() = 0;
    virtual TSmartPtr<IProduct2> CreateProduct2() = 0;
};
 
// 抽象工厂类
 
class CAFactory : public IAbstractFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CAProduct;
    }
 
    virtual TSmartPtr<IProduct2> CreateProduct2()
    {
        return new CAProduct2;
    }
};
 
class CBFactory : public IAbstractFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CBProduct;
    }
 
    virtual TSmartPtr<IProduct2> CreateProduct2()
    {
        return new CBProduct2;
    }
};
 
class CCFactory : public IAbstractFactory
{
public:
    virtual TSmartPtr<IProduct> CreateProduct()
    {
        return new CCProduct;
    }
 
    virtual TSmartPtr<IProduct2> CreateProduct2()
    {
        return new CCProduct2;
    }
};
 
//////////////////////////////////////////////////////////////////
 
// 主函数
int _tmain(int argc, _TCHAR* argv[])
{
    _tcout << _T("简单工厂:") << endl;
    // 利用简单工厂创建产品
    CSimpleFactory::CreateProduct(_T("A"))->Func();        // 创建产品1A并调用
    CSimpleFactory::CreateProduct2(_T("A"))->Func2();    // 创建产品2A并调用
    CSimpleFactory::CreateProduct(_T("B"))->Func();        // 创建产品1B并调用
    CSimpleFactory::CreateProduct2(_T("B"))->Func2();    // 创建产品2B并调用
    CSimpleFactory::CreateProduct(_T("C"))->Func();        // 创建产品1C并调用
    CSimpleFactory::CreateProduct2(_T("C"))->Func2();    // 创建产品2C并调用
 
    _tcout << _T("抽象工厂:") << endl;
    TSmartPtr<IAbstractFactory> c_p_factory;
    // 利用抽象工厂创建产品
    c_p_factory = new CAFactory;
    c_p_factory->CreateProduct()->Func();                // 创建产品1A并调用
    c_p_factory->CreateProduct2()->Func2();                // 创建产品2A并调用
    c_p_factory = new CBFactory;
    c_p_factory->CreateProduct()->Func();                // 创建产品1B并调用
    c_p_factory->CreateProduct2()->Func2();                // 创建产品2B并调用
    c_p_factory = new CCFactory;
    c_p_factory->CreateProduct()->Func();                // 创建产品1C并调用
    c_p_factory->CreateProduct2()->Func2();                // 创建产品2C并调用
 
    return 0;
}
 
//////////////////////////////////////////////////////////////////
/*
    抽象工厂模式的重点思想在于面向接口编程.
    它提供了一个创建一系列相关或相互依赖对象的接口,运用抽象工厂模式的关键点在于应对"多系列对象创建"的需求变化.
*/
//////////////////////////////////////////////////////////////////


更多内容请访问:http://darkc.at

抱歉!评论已关闭.