C++工厂方法之对象创建型模式详解

 更新时间:2022年03月11日 09:47:56   作者:早睡身体好hh  
这篇文章主要为大家详细介绍了C++对象创建型模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

1.代码示例

工厂方法模式,简称工厂模式或者多态工厂模式。与简单工厂模式相比,引入了更多的新类,灵活性更强,实现也更加复杂。符合开闭原则,付出的代价是需要新增加多个新的工厂类。

如下,M_UndeadFactoryM_ElementFactoryM_MechanicFactory 类有一个共同的父类 M_ParFactory(工厂抽象类)。

M_ParFactory 类中的 createMonster 成员函数其实就是个工厂方法,工厂方法模式的名字也是由此而来。

#include <iostream>
using namespace std;
// 怪物父类
class Monster
{
public:
	// 构造函数
	Monster(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack) {}
	virtual ~Monster() {} // 父类的析构函数应该为虚函数
protected: // 可能被子类访问的成员,所以用protected修饰
	int m_life; // 生命值
	int m_magic; // 魔法值
	int m_attack; // 攻击力
};
// 亡灵类怪物
class M_Undead : public Monster
{
public:
	// 构造函数
	M_Undead(int life, int magic, int attack) : Monster(life, magic, attack)
	{
		cout << "一个亡灵类怪物来到了这个世界" << endl;
	}
	// 其他代码略
};
// 元素类怪物
class M_Element : public Monster
{
public:
	// 构造函数
	M_Element(int life, int magic, int attack) : Monster(life, magic, attack)
	{
		cout << "一个元素类怪物来到了这个世界" << endl;
	}
	// 其他代码略
};
// 机械类怪物
class M_Mechanic : public Monster
{
public:
	// 构造函数
	M_Mechanic(int life, int magic, int attack) : Monster(life, magic, attack)
	{
		cout << "一个机械类怪物来到了这个世界" << endl;
	}
	// 其他代码略
};
// 所有工厂类的父类
class M_ParFactory
{
public:
	virtual Monster* createMonster() = 0; // 具体实现在子类中进行
	virtual ~M_ParFactory() {} // 父类的析构函数应该为虚函数
};
// M_Undead怪物类型的工厂,生产M_Undead类型怪物
class M_UndeadFactory : public M_ParFactory
{
public:
	virtual Monster* createMonster()
	{
		Monster *ptmp = new M_Undead(300, 50, 80); // 创建亡灵类怪物
		//这里可以增加一些其他业务代码
		return ptmp;
	}
};
// M_Element怪物类型的工厂,生产M_Element类型怪物
class M_ElementFactory : public M_ParFactory
{
public:
	virtual Monster* createMonster()
	{
		return new M_Element(200, 80, 100); // 创建元素类怪物
	}
};
// M_Mechanic怪物类型的工厂,生产M_Mechanic类型怪物
class M_MechanicFactory : public M_ParFactory
{
public:
	virtual Monster* createMonster()
	{
		return new M_Mechanic(400, 0, 110); // 创建机械类怪物
	}
};
// 全局函数:用于创建怪物对象
// 注意:形参的类型是工厂父类类型的指针,返回类型是怪物父类类型的指针
Monster* Gbl_CreateMonster(M_ParFactory* factory)
{
	return factory->createMonster();
	// createMonster虚函数扮演了多态new的行为,factory指向的具体怪物工厂类不同,创建的怪物对象也不同
}
int main()
{
	M_ParFactory* p_ud_fy = new M_UndeadFactory(); // 多态工厂,注意指针类型
	Monster* pM1 = Gbl_CreateMonster(p_ud_fy); // 产生了一只亡灵类怪物,也是多态,注意返回类型
	// 当然,这里也可以直接写成 Monster *pM1 = p_ud_fy->createMonster();
	M_ParFactory* p_elm_fy = new M_ElementFactory();
	Monster *pM2 = Gbl_CreateMonster(p_elm_fy); // 产生了一只元素类怪物
	M_ParFactory* p_mec_fy = new M_MechanicFactory();
	Monster* pM3 = Gbl_CreateMonster(p_mec_fy); // 产生了一只机械类怪物
	// 释放工厂
	delete p_ud_fy;
	delete p_elm_fy;
	delete p_mec_fy;
	// 释放怪物
	delete pM1;
	delete pM2;
	delete pM3;
	return 0;
}

简单工厂模式把创建对象这件事放到了一个统一的地方来处理,弹性比较差。而工厂方法模式相当于建立了一个程序实现框架,从而让子类来决定对象如何创建。

工厂方法模式往往需要创建一个与产品等级结构(层次)相同的工厂等级结构,这也增加了新类的层次结构和数目。

如果不想创建太多工厂类,又想封装变化,则可以创建怪物工厂子类模板。

#include <iostream>
using namespace std;
// 怪物父类
class Monster
{
public:
	// 构造函数
	Monster(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack) {}
	virtual ~Monster() {} // 父类的析构函数应该为虚函数
protected: // 可能被子类访问的成员,所以用protected修饰
	int m_life; // 生命值
	int m_magic; // 魔法值
	int m_attack; // 攻击力
};
// 亡灵类怪物
class M_Undead : public Monster
{
public:
	// 构造函数
	M_Undead(int life, int magic, int attack) : Monster(life, magic, attack)
	{
		cout << "一个亡灵类怪物来到了这个世界" << endl;
	}
	// 其他代码略
};
// 元素类怪物
class M_Element : public Monster
{
public:
	// 构造函数
	M_Element(int life, int magic, int attack) : Monster(life, magic, attack)
	{
		cout << "一个元素类怪物来到了这个世界" << endl;
	}
	// 其他代码略
};
// 机械类怪物
class M_Mechanic : public Monster
{
public:
	// 构造函数
	M_Mechanic(int life, int magic, int attack) : Monster(life, magic, attack)
	{
		cout << "一个机械类怪物来到了这个世界" << endl;
	}
	// 其他代码略
};
// 所有工厂类的父类
class M_ParFactory
{
public:
	virtual Monster* createMonster() = 0; // 具体实现在子类中进行
	virtual ~M_ParFactory() {} // 父类的析构函数应该为虚函数
};
template <typename T>
class M_ChildFactory :public M_ParFactory
{
public:
	virtual Monster* createMonster()
	{
		return new T(300, 50, 80); //如果需要不同的值则可以通过createMonster的形参将值传递进来
	}
};
int main()
{
	M_ChildFactory<M_Undead> myFactory;
	Monster* pM10 = myFactory.createMonster();
	// 释放资源
	delete pM10;
	getchar();
	return 0;
}

UML 如下:

在这里插入图片描述

2.工厂方法模式的定义(实现意图)

定义一个用于创建对象的接口(M_ParFactory类中的createMonster成员函数),由子类(M_UndeadFactoryM_ElementFactoryM_MechanicFactory)决定要实例化的类是哪一个。该模式使得某个类(M_UndeadM_ElementM_Mechanic)的实例化延迟到子类(M_UndeadFactoryM_ElementFactoryM_MechanicFactory)。

一般可以认为,将简单工厂模式的代码经过把工厂类进行抽象改造成符合开闭原则后的代码,就变成了工厂方法模式的代码。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!  

相关文章

  • C语言实现小猫钓鱼算法

    C语言实现小猫钓鱼算法

    这篇文章主要为大家详细介绍了C语言实现小猫钓鱼算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Linux vmstat命令实战详细解析

    Linux vmstat命令实战详细解析

    这个命令是我查看Linux/Unix最喜爱的命令,一个是Linux/Unix都支持,二是相比top,我可以看到整个机器的CPU,内存,IO的使用情况,而不是单单看到各个进程的CPU使用率和内存使用率(使用场景不一样)
    2013-09-09
  • C语言入门篇--初识C语言及数据类型

    C语言入门篇--初识C语言及数据类型

    本篇文章是c语言基础篇,主要为大家介绍了C语言的基本类型,为大家介绍了什么是C语言,希望可以帮助大家快速入门c语言的世界,更好的理解c语言
    2021-08-08
  • C# interface与delegate效能比较的深入解析

    C# interface与delegate效能比较的深入解析

    本篇文章是对C#中interface与delegate的效能比较进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • VScode + keil开发环境搭建安装使用过程

    VScode + keil开发环境搭建安装使用过程

    这篇文章主要介绍了VScode + keil开发环境搭建及安装使用过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • C语言goto语句简单使用详解

    C语言goto语句简单使用详解

    C语言中提供了可以随意滥用的 goto语句和标记跳转的标号,本文主要介绍了C语言goto语句简单使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C语言实现教务管理系统

    C语言实现教务管理系统

    这篇文章主要为大家详细介绍了C语言实现教务管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C调用C++代码的方法步骤

    C调用C++代码的方法步骤

    本文主要介绍了C调用C++代码的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • C/C++使用Zlib实现文件的压缩与解压

    C/C++使用Zlib实现文件的压缩与解压

    zlib 是一个开源的数据压缩库,旨在提供高效、轻量级的压缩和解压缩算法,本文将介绍如何使用 zlib 库进行数据的压缩和解压缩,以及如何保存和读取压缩后的文件,感兴趣的可以了解下
    2023-11-11
  • C++数据结构深入探究栈与队列

    C++数据结构深入探究栈与队列

    栈和队列,严格意义上来说,也属于线性表,因为它们也都用于存储逻辑关系为 "一对一" 的数据,但由于它们比较特殊,本章讲解分别用队列实现栈与用栈实现队列
    2022-05-05

最新评论