AkiraZheng's Time.

设计模式2:工厂方法模式(C++)

Word count: 1.3kReading time: 5 min
2024/02/02

前言

本文中所有设计模式Github代码
其中本文工厂方法模式-简单工厂相关代码在FactoryMethod_SimpleFactory.h文件中
本文工厂方法模式-工厂方法相关代码在FactoryMethod.h文件中

工厂方法中,一般一个应用中每一个工厂系列只需要一个ConcreteFactory类的实例,因此设计工厂类时,通常将其设计为单例模式

一、简单工厂

1. 什么是简单工厂

简单工厂中,设计的核心思想是将对象的创建和使用分离,即将对象的创建交给工厂类(非抽象类),而将对象的使用交给客户端。

简单工厂设计中,工厂类采用通常使用switch-case语句来根据不同的条件创建不同的对象,这样的设计是不符合开闭原则的,因为每次添加新的产品都需要修改工厂类的代码(在switch-case语句中加入新产品的create代码),代码灵活性很差。

因此需要将简单工厂的设计升级为工厂方法模式,在工厂类中使用纯虚函数方法(createProduct方法)将其设计成抽象类。

开闭原则:对扩展开放、对修改关闭;
也就是说,我们可以添加代码,但是添加代码的时候不能够对现有的代码进行修改

2. 简单工厂的代码

  • 代码UML类图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*产品类的设计:抽象基类*/
class Phone{
// 产品基类
public:
Phone(string name):_phone_name(name){};
virtual void show() = 0;
virtual ~Phone(){}; //基类应该被声明为虚析构函数
protected:
string _phone_name;
};
class Iphone:public Phone{
// 产品派生类
public:
Iphone(string name):Phone(name){};
void show(){
cout << "I have a phone named: " << _phone_name << endl;
}
};
class HuaWei:public Phone{
// 产品派生类
public:
HuaWei(string name):Phone(name){};
void show(){
cout << "I have a phone named: " << _phone_name << endl;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*工厂类的设计:非抽象类*/
class PhoneFactory{
// 工厂类
public:
enum phone_type{
IPHONE,
HUAWEI
};
Phone* createPhone(int type){
switch (type)
{
case IPHONE:
return new Iphone("iphone");
case HUAWEI:
return new HuaWei("huawei");
default:
return nullptr;
}
}
};
1
2
3
4
5
6
7
8
9
/*测试函数*/
/*测试函数*/
void testFactory_simpleFactory(){
PhoneFactory factory;
Phone* p1 = factory.createPhone(PhoneFactory::IPHONE);
Phone* p2 = factory.createPhone(PhoneFactory::HUAWEI);
p1->show();
p2->show();
}

二、工厂方法模式

  1. 工厂方法相较于简单工厂的改进

    • 简单工厂中,产品基类抽象的,而工厂类非抽象的,这样的设计是不符合开闭原则的
    • 工厂模式将工厂基类也设计成一个抽象的,并针对不同的产品类型设计不同的工厂派生类,这样在用户使用的时候可以很有目的性地选择对应的工厂派生类进行初始化,而不是简单工厂中的switch-case语句的随机性选择。
  2. 工厂方法的缺点

    • 工厂方法模式的缺点是每增加一个产品,就需要增加一个产品工厂类,这样会导致工厂类的数量增加,增加了系统的复杂度。
    • 工厂方法中的工厂类只有一个create方法,因此当产品不断增加时,需要的工厂派生类也不断增加,这样不利于管理,因此需要将工厂方法模式升级为抽象工厂模式

三、工厂方法模式的实现代码(C++)

tips:使用智能指针需要引入头文件#include <memory>,使用普通指针new之后记得delete

  • 代码UML类图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*产品类的设计:抽象基类*/
//1. 产品抽象基类
class Phone{
// 产品基类
public:
Phone(string name):_phone_name(name){};
virtual void show() = 0;
virtual ~Phone(){}; //基类应该被声明为虚析构函数
protected:
string _phone_name;
};
//2. 产品派生具体类
class Iphone:public Phone{
// 产品派生类
public:
Iphone(string name):Phone(name){};
void show(){
cout << "I have a phone named: " << _phone_name << endl;
}
};
class HuaWei:public Phone{
// 产品派生类
public:
HuaWei(string name):Phone(name){};
void show(){
cout << "I have a phone named: " << _phone_name << endl;
}
};
  • 说明:在工厂抽象类设计时,具体工厂一一对应用于new一个具体产品,当具体工厂类创建时,不同具体产品要求的的参数不同时,可以将参数也设计成一个抽象基类,这样在具体工厂类中可以根据不同的参数创建不同的产品。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    /*工厂类的设计:抽象基类*/
    //1. 工厂抽象基类
    class PhoneFactory{
    // 工厂类
    public:
    virtual Phone* createPhone(string name) = 0;
    virtual ~PhoneFactory(){}; //基类应该被声明为虚析构函数
    };
    //2. 工厂派生具体类
    class IphoneFactory:public PhoneFactory{
    // 工厂派生类
    public:
    Phone* createPhone(string name){
    return new Iphone(name);
    }
    };
    class HuaWeiFactory:public PhoneFactory{
    // 工厂派生类
    public:
    Phone* createPhone(string name){
    return new HuaWei(name);
    }
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*测试函数*/
    void testFactory_factoryMethod(){
    unique_ptr<PhoneFactory> iPhoneFactory(new IphoneFactory());
    unique_ptr<PhoneFactory> huaweiFactory(new HuaWeiFactory());
    unique_ptr<Phone> iphone(iPhoneFactory->createPhone("iphone"));//通过单独的Iphone工厂创建对应产品
    unique_ptr<Phone> huawei(huaweiFactory->createPhone("huawei"));//通过单独的HuaWei工厂创建对应产品
    iphone->show();
    huawei->show();
    }

四、Reference

  1. C++工厂模式(简单工厂、工厂方法、抽象工厂)
  2. 工厂方法模式
CATALOG
  1. 前言
  2. 一、简单工厂
    1. 1. 什么是简单工厂
    2. 2. 简单工厂的代码
  3. 二、工厂方法模式
  4. 三、工厂方法模式的实现代码(C++)
  5. 四、Reference