Chapter4—工厂方法模式

工厂方法模式

1 概念

工厂方法模式是指一个工厂接口用来声明创建产品对象,具体创建的产品对象由派生类工厂实现,达到一个工厂生产一种产品对象的目的。工厂方法很好地解决了一个工厂进行一种产品的生产,且各个产品又不互相依赖的问题。

2 意图(Intent)

定义了一个创建对象的抽象方法,由子类决定要实例化的类,工厂方法模式将对象的实例化推迟到子类。

3 动机(Motivate)

考虑到这样一个系统,电子产品工厂生产可以生产一个具体的电子产品,如手机、平板等。吐过我们需要新增一个产品,比如智能手表,除了需要新增产品类外,还需要通过修改工厂类代码来实现,这样就违法了开闭原则。我们通过定义一个用于创建对象的接口,让子类决定实例化创建哪一个类。,工厂方法模式使一个类的实例化延迟到其子类。

4 类图结构

5 角色定义

  • Product(产品):所有产品的父类,可以是抽象类或接口。
  • ConcreteProduct(具体产品):由产品Product派生出的产品子类,可以有多个产品子类。
  • Factory(工厂):定义工厂方法的工厂接口,当然也可以是抽象类,它使顶级工厂制造方法抽象化,标准统一化。
  • ConcreteFactory(具体工厂):实现了工厂接口的工厂实现类,并决定工厂方法中具体返回哪种产品子类的实例。

6 程序示例

基本工厂方法和产品

产品基类BaseProduct

cpp 复制代码
class BaseProduct
{
public:
    BaseProduct() = default;
    virtual ~BaseProduct();

public:
    virtual void SomeMethod() = 0;
};

BaseProduct::~BaseProduct()
{
    qDebug() << "Destructor BaseProduct";
}

具体产品类ProductA

CPP 复制代码
class ProductA: public BaseProduct
{
public:
    ProductA() = default;
    ~ProductA() = default;

public:
    void SomeMethod() override;
};

void ProductA::SomeMethod()
{
    qDebug() << "ProductA SomeMethod";
}

具体产品类ProductB

cpp 复制代码
class ProductB: public BaseProduct
{
public:
    ProductB() = default;
    ~ProductB() = default;

public:
    void SomeMethod() override;
};

void ProductB::SomeMethod()
{
    qDebug() << "ProductB SomeMethod";
}

工厂基类BaseFactory,我们抽象的是创建产品的方法

cpp 复制代码
class BaseFactory
{
public:
    BaseFactory() = default;
    virtual ~BaseFactory();

public:
    virtual BaseProduct* CreateProduct() = 0;
};

BaseFactory::~BaseFactory()
{
    qDebug() << "Destructor BaseFactory";
}

具体工厂类FactoryA

cpp 复制代码
class FactoryA : public BaseFactory
{
public:
    FactoryA() = default;
    ~FactoryA() = default;

public:
    BaseProduct* CreateProduct() override;
};

BaseProduct *FactoryA::CreateProduct()
{
    return new ProductA();
}

具体工厂类FactoryB

cpp 复制代码
class FactoryB : public BaseFactory
{
public:
    FactoryB() = default;
    ~FactoryB() = default;

public:
    BaseProduct* CreateProduct() override;
};

BaseProduct *FactoryB::CreateProduct()
{
    return new ProductB();
}

测试工厂模式程序

cpp 复制代码
// 非智能指针模式
void TestFactory()
{
    BaseFactory* pFactorA = new FactoryA();
    BaseProduct* pProductA = pFactorA->CreateProduct();

    pProductA->SomeMethod();

    delete pFactorA;
    delete pProductA;
}

// 智能指针模式
void TestFactory()
{
    std::unique_ptr<BaseFactory> upFactorA = std::make_unique<FactoryA>();

    std::unique_ptr<BaseProduct> upProductA;
    upProductA.reset(upFactorA->CreateProduct());

    upProductA->SomeMethod();
}

生产手机和平板的工厂

类的结构图

颜色较浅的为高层、抽象层,相对稳定,也就是我们所谓的很少变化的模块,而颜色较深的为具体层,稳定性相对较差,变化会比较多。

代码示例:

电子产品基类

cpp 复制代码
/**
 * @brief 电子产品基类
 */
class ElectronicProduct
{
public:
    ElectronicProduct() = default;
    virtual ~ElectronicProduct() = default;

public:
    virtual void Show() = 0;
};

手机类

cpp 复制代码
/**
 * @brief 手机类
 */
class PhoneProduct: public ElectronicProduct
{
public:
    PhoneProduct() = default;
    ~PhoneProduct() = default;

public:
    void Show() override;
};

void PhoneProduct::Show()
{
    qDebug() << "Phone Show";
}

平板类

cpp 复制代码
/**
 * @brief 平板类
 */
class PadProduct: public ElectronicProduct
{
public:
    PadProduct() = default;
    ~PadProduct() = default;

public:
    void Show() override;
};

void PadProduct::Show()
{
    qDebug() << "Pad Show";
}

工厂接口类,我们抽象的是创建电子产品的方法

cpp 复制代码
/**
 * @brief 工厂接口类
 */
class IFactory
{
public:
    IFactory() = default;
    virtual ~IFactory() = default;

public:
    virtual ElectronicProduct* CreateProduct() = 0;
};

手机工厂类,也是具体工厂的角色

cpp 复制代码
/**
 * @brief 手机工厂类
 */
class PhoneFactory : public IFactory
{
public:
    PhoneFactory() = default;
    ~PhoneFactory() = default;

public:
    ElectronicProduct* CreateProduct() override;
};

ElectronicProduct *PhoneFactory::CreateProduct()
{
    return new PhoneProduct();
}

平板工厂类,也是具体工厂的角色

cpp 复制代码
/**
 * @brief 平板工厂类
 */
class PadFactory : public IFactory
{
public:
    PadFactory() = default;
    ~PadFactory() = default;

public:
    ElectronicProduct* CreateProduct() override;
};

ElectronicProduct* PadFactory::CreateProduct()
{
    return new PadProduct();
}

测试函数

cpp 复制代码
void ClientTest()
{
    IFactory* pPhoneFactory = new PhoneFactory();
    IFactory* pPadFactory = new PadFactory();

    ElectronicProduct* pPhone = pPhoneFactory->CreateProduct();
    ElectronicProduct* pPad = pPadFactory->CreateProduct();

    pPhone->Show();
    pPad->Show();

    delete pPhoneFactory;
    delete pPadFactory;

    delete pPhone;
    delete pPad;
}

7 思考小结

工厂方法模式让对象的创建和实现相互独立,它对工厂制造方法进行接口规范化,以允许子类工厂决定具体制造哪类产品的实例,可以达到松耦合的目的;具体的工厂生成具体的产品,方便理解程序的结构,但是缺点也很明显,如果要增加新的产品类,还需要增加对应的新工厂。

怎样记住工厂方法模式的结构,我们只需要记住两个抽象方向,工厂抽象的方向为创建产品,产品抽象的方向为不同产品,工厂抽象类依赖产品抽象类,也就是所谓的高层模块依赖高层模块,而具体的工厂依赖具体的产品,也就是低层模块依赖低层模块,这样达到高层(稳定)和低层(不稳定)的隔离。

8 附录-简单工厂

简单工厂只对产品进行抽象,让工厂对象通过其自身方法中的形参变量决定创建产品的类型。

程序示例

工厂创建产品函数的枚举

cpp 复制代码
enum E_PRODUCT_TYPE
{
    PRODUCT_A,
    PRODUCT_B,
    PRODUCT_C
};

产品基类

cpp 复制代码
class BaseProduct
{
public:
    BaseProduct() = default;
    virtual ~BaseProduct();

public:
    virtual void Show() = 0;
};

BaseProduct::~BaseProduct()
{
    // ...
}

产品A类

cpp 复制代码
class ProductA : public BaseProduct
{
public:
    ProductA() = default;
    ~ProductA() = default;

public:
    void Show() override;
};

void ProductA::Show()
{
    qDebug() << "Show ProductA";
}

产品B类

cpp 复制代码
class ProductB : public BaseProduct
{
public:
    ProductB() = default;
    ~ProductB() = default;

public:
    void Show() override;
};

void ProductB::Show()
{
    qDebug() << "Show ProductB";
}

产品C类

cpp 复制代码
class ProductC : public BaseProduct
{
public:
    ProductC() = default;
    ~ProductC() = default;

public:
    void Show() override;
};

void ProductC::Show()
{
    qDebug() << "Show ProductC";
}

工厂类部分

cpp 复制代码
class Factory
{
public:
    Factory() = default;
    ~Factory() = default;

public:
    BaseProduct* CreateProduct(E_PRODUCT_TYPE eProductType);
};

BaseProduct* Factory::CreateProduct(E_PRODUCT_TYPE eProductType)
{
    switch(eProductType)
    {
    case PRODUCT_A:
        return new ProductA();
    case PRODUCT_B:
        return new ProductB();
    case PRODUCT_C:
        return new ProductC();
    default:
        return nullptr;
    }
}

测试函数

cpp 复制代码
void TestFactory()
{
    std::unique_ptr<Factory> upFactory = std::make_unique<Factory>();

    BaseProduct* pProductA = upFactory->CreateProduct(PRODUCT_A);
    BaseProduct* pProductB = upFactory->CreateProduct(PRODUCT_B);
    BaseProduct* pProductC = upFactory->CreateProduct(PRODUCT_C);

    pProductA->Show();		// Show ProductA
    pProductB->Show();		// Show ProductB
    pProductC->Show();		// Show ProductC

    delete pProductA;
    delete pProductB;
    delete pProductC;
}
相关推荐
青草地溪水旁2 小时前
设计模式(C++)详解—工厂方法模式(2)
c++·工厂方法模式
深耕AI2 小时前
MFC 图形设备接口详解:小白从入门到掌握
c++·mfc
青草地溪水旁2 小时前
设计模式(C++)详解—工厂方法模式(1)
c++·工厂方法模式
·白小白2 小时前
C++类(上)默认构造和运算符重载
c++·学习
染指11103 小时前
11.ImGui-加载字体和中文
c++·windows·imgui
浩浩乎@4 小时前
【openGLES】纹理
c++·opengles
叫我龙翔4 小时前
【设计模式】从游戏角度开始了解设计模式 --- 抽象工厂模式
c++·游戏·设计模式
青草地溪水旁4 小时前
设计模式(C++)详解—单例模式(1)
c++·单例模式
HMBBLOVEPDX5 小时前
C++(深拷贝和浅拷贝)
开发语言·c++·浅拷贝和深拷贝