工厂方法(Factory Method):对象创建型模式

2023-10-30

1.代码示例

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

如下,M_UndeadFactory、M_ElementFactory、M_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_UndeadFactory、M_ElementFactory、M_MechanicFactory)决定要实例化的类是哪一个。该模式使得某个类(M_Undead、M_Element、M_Mechanic)的实例化延迟到子类(M_UndeadFactory、M_ElementFactory、M_MechanicFactory)。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

工厂方法(Factory Method):对象创建型模式 的相关文章

  • 【设计模式】工厂方法模式(C#)

    设计模式 工厂方法模式 1 概述 针对简单工厂中的缺点 使用工厂方法模式就可以完美的解决 完全遵循开闭原则 定义一个用于创建对象的接口 让子类决定实例化哪个产品类对象 工厂方法使一个产品类的实例化延迟到其工厂的子类 工厂方法模式的主要角色
  • 6.11行为型---解释器模式

    在软件开发中 会遇到有些问题多次重复出现 而且有一定的相似性和规律性 如果将它们归纳成一种简单的语言 那么这些问题实例将是该语言的一些句子 这样就可以用 编译原理 中的解释器模式来实现了 虽然使用解释器模式的实例不是很多 但对于满足以上特点
  • [大话设计模式C++版] 第8章 雷锋依然在人间 —— 工厂方法模式

    源码可以在这里找到 大话设计模式C 版 模拟大学生学雷锋 main cpp class LeiFeng public void Sweep cout lt lt 扫地 lt lt endl void Wash cout lt lt 洗衣 l
  • 设计模式(四)单例和简单工厂的融合

    前面三篇文章介绍了三种模式 单例 简单工厂和工厂方法 其中 简单工厂和工厂方法都是基于同一个实际问题 但是 这个例子里有几个问题 1 职工的创建在main函数中 不合理 可能多个函数都会需要访问职工信息 2 职工是程序直接创建的 不合理 一
  • 工厂方法(Factory Method):对象创建型模式

    文章目录 1 代码示例 2 工厂方法模式的定义 实现意图 1 代码示例 工厂方法模式 简称工厂模式或者多态工厂模式 与简单工厂模式相比 引入了更多的新类 灵活性更强 实现也更加复杂 符合开闭原则 付出的代价是需要新增加多个新的工厂类 如下
  • 3.5设计模式——————接口隔离原则——面向对象设计原则

    接口隔离原则的定义 接口隔离原则 Interface Segregation Principle ISP 要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口 让接口中只包含客户感兴趣的方法 2002 年罗伯特 C 马丁给 接口隔离原则
  • 工厂模式(分简单工厂模式、工厂方法模式、抽象工厂模式)

    1 工厂模式概述 1 1 简单工厂模式 简单工厂模式是一种创建型设计模式 它实现了创建对象的功能 但不使用任何具体类的名称 客户端通过调用工厂类的静态方法来创建一个具体的对象 无需关心对象创建的细节 1 2 工厂方法模式 工厂方法模式是一种
  • 设计模式之工厂方法模式

    工厂方法模式 根据简单工厂模式的案例可知 如果我们想要添加一种立方运算 只需要创建一个立方运算类继承运算类 然后在工厂类中添加一个case分支用于逻辑判断 问题在于 我们在进行功能扩展的同时 也修改了工厂类中的代码 这很明显违背了开放 封闭
  • 设计模式-工厂方法模式

    文章目录 前言 工厂方法模式概述 使用场景 工厂方法模式优缺点 Java代码示例 前言 当我们面临需要创建不同类型对象的需求时 通常会使用工厂方法模式 工厂方法模式是一种创建型设计模式 它提供了一种将对象的创建与使用分离的方法 允许我们在不
  • 设计模式(三)工厂方法模式

    前一篇文章介绍了简单工厂模式 留下了一个疑问 如果需要扩展员工等级 有没有不修改既有接口的方式 答案就是工厂方法模式 既然员工的职级可以扩展 那创建对应职级员工的工厂是不是也可以扩展 工厂基类提供一个接口获取具体的产品 一旦有新的产品 就创
  • java设计模式——工厂方法模式(Factory Method Pattern)

    简单工厂模式虽然简单 但也受到很大限制 扩展性太差 当系统中需要引入新产品时 由于静态工厂方法通过所传入参数的不同来创建不同的产品 这必定要修改工厂类的源代码 将违背 开闭原则 如何实现增加新产品而不影响已有代码 工厂方法模式应运而生 本文
  • 【已解决】Factory method ‘redisConnectionFactory‘ threw exception; nested exception is java.lang.

    Factory method redisConnectionFactory threw exception nested exception is java lang NoClassDefFoundError org apache comm
  • 5.4结构型模式—————装饰模式

    装饰模式的定义与特点 装饰 Decorator 模式的定义 指在不改变现有对象结构的情况下 动态地给该对象增加一些职责 即增加其额外功能 的模式 它属于对象结构型模式 装饰 Decorator 模式的主要优点有 采用装饰模式扩展对象的功能比
  • 5.0结构型模式—概述

    结构型模式描述如何将类或对象按某种布局组成更大的结构 它分为类结构型模式和对象结构型模式 前者采用继承机制来组织接口和类 后者釆用组合或聚合来组合对象 由于组合关系或聚合关系比继承关系耦合度低 满足 合成复用原则 所以对象结构型模式比类结构
  • 5.1结构型模式————代理模式

    在有些情况下 一个客户不能或者不想直接访问另一个对象 这时需要找一个中介帮忙完成某项任务 这个中介就是代理对象 例如 购买火车票不一定要去火车站买 可以通过 12306 网站或者去火车票代售点买 又如找女朋友 找保姆 找工作等都可以通过找中
  • 4.5创建型模式—————建造者模式(Bulider模式)

    在软件开发过程中有时需要创建一个复杂的对象 这个复杂对象通常由多个子部件按一定的步骤组合而成 例如 计算机是由 OPU 主板 内存 硬盘 显卡 机箱 显示器 键盘 鼠标等部件组装而成的 采购员不可能自己去组装计算机 而是将计算机的配置要求告
  • 模板方法(Template Method):类行为型模式

    文章目录 1 设计模式 Design Pattern 1 1 概述 1 2 分类 2 模板方法 Template Method 类行为型模式 2 1 代码示例 2 2 模板方法模式的定义 实现意图 1 设计模式 Design Pattern
  • Gof23设计模式之工厂方法模式和抽象工厂模式

    在java中 万物皆对象 这些对象都需要创建 如果创建的时候直接new该对象 就会对该对象耦合严重 假如我们要更换对象 所有new对象的地方都需要修改一遍 这显然违背了软件设计的开闭原则 如果我们使用工厂来生产对象 我们就只和工厂打交道就可
  • 6.4行为型模式——责任链模式

    在现实生活中 常常会出现这样的事例 一个请求有多个对象可以处理 但每个对象的处理条件或权限不同 例如 公司员工请假 可批假的领导有部门负责人 副总经理 总经理等 但每个领导能批准的天数不同 员工必须根据自己要请假的天数去找不同的领导签名 也
  • 6.10行为型---备忘录模式

    每个人都有犯错误的时候 都希望有种 后悔药 能弥补自己的过失 让自己重新开始 但现实是残酷的 在计算机应用中 客户同样会常常犯错误 能否提供 后悔药 给他们呢 当然是可以的 而且是有必要的 这个功能由 备忘录模式 来实现 其实很多应用软件都

随机推荐

  • 仪表识别之数字表识别

    转自 https blog csdn net huneng1991 article details 82049207 这篇文章讲述了仪表上的数字表的识别 看图片效果还是挺好的 这里记录一下备用 2 识别检测方法 这篇文章主要用的方法是机器学
  • “猜数字“游戏,系统随机生成一个[1,100]的数字,由用户输入数字后,计算机提示输入数字“偏大”、“偏小”,并记录猜数次数

    import java util Scanner public class Demo public static void main String args TODO Auto generated method stub Scanner i
  • [C语言]分支语句:if语句、switch语句

    分支语句也称为选择结构 条件判断语句 顾名思义 要么选择A 要么选择B 或选择其他的一种结构 在c语言中 常见的分支语句分别有 if语句和switch语句 目录 1 if语句 1 1if语句的结构 1 2if语句的注意点 2 switch语
  • 【MATLAB】rem和mod函数的区别

    求整数x y的余数 rem x y 求模 mod x y 如果x和y的符号相同 同为 同为 那么rem x y mod x y 正数与正数 负数与负数 取整结果两个函数效果一样 如果x和y的符号相反 那么mod x y rem x y y
  • 存储过程的概念,函数与存储过程的区别

    存储过程 为了完成特定功能的sql语句集进行编译优化后 存储在数据库服务器中 用户通过指定存储过程的名字来调用执行 区别 本质上没有区别 1 存储过程作为一个独立部分 函数可以作为查询语句的一个部分 2 存储过程功能较为复杂 函数功能针对性
  • Linux系统下安装Python爬虫环境+模拟浏览器插件

    一 服务器版本 Centos7以上版本 二 配置python环境 1 安装依赖包 yum y install gcc gcc c yum y install zlib zlib devel yum y install bzip2 bzip2
  • 如何通过gradle来导入jar包

    很多android项目在lib文件夹下看不到任何的jar包 但是项目中确实导入了很多的第三方jar包 这里我们来看看androidstudio通过gradle来导入jar包的方法 首先我们需要进入ProjectStructure界面 打开这
  • C8051 不能写数据

    问题 使用C8051f520芯片 在线调试发现不能给变量赋值 解决 芯片ram只有256B 我在keil设置了pdata 改成data就行了 网友资料显示 pdATa 外部扩展RAM的低256个字节 地址出现在A0 A7的上时读写 用mov
  • ipad未能与itunes连接到服务器,为什么无法连接到iTunes Store?iPhone/iPad解决方法

    一些用户在使用iPhone时 偶尔会发现在登录Apple ID或者是在Apple Store中下载软件时 会显示无法连接到iTunes Store 出现这个提示 也就无法在Apple Store中进行相关操作了 那么 大家知道为什么无法连接
  • Eigen库中vector.transpose()函数什么意思

    在使用Eigen库时 我们阅读源码的时候可能看到在输出 显示 一个向量时 有如下表示形式 定义一个向量 Vector3d p2 打印该向量 cout lt lt p2 lt lt endl 列向量显示 cout lt lt p2 trans
  • 【2D标注】cvat-canvas添加标尺线

    一 场景概述 在使用cvat canvas做2D标注开发时 有时我们需要对2D图形添加一些标尺线 例如前方距离当前摄像头的距离标尺 这时候我们需要添加标尺线 基于cvat canvas现有的框架设计模式 实现逻辑如下 在canvasView
  • 16-4_Qt 5.9 C++开发指南_Qt 应用程序的发布

    文章目录 1 应用程序发布方式 2 Windows 平台上的应用程序发布 1 应用程序发布方式 用 Qt 开发一个应用程序后 将应用程序提供给用户在其他计算机上使用就是应用程序的发布 应用程序发布一般会提供一个安装程序 将应用程序的可执行文
  • 取消idea双击shift时出现的搜索框

    快捷键 Ctrl Shift A 有可能没反应 Help gt Find Action 输入registry 选择第一个 找到ide suppress double click handler 勾选它 双击shift不会再弹出搜索框
  • reportlab 使用中文报错 reportlab.pdfbase.ttfonts.TTFError: Not a recognized TrueType font

    使用reportlab 使用中文报错过程中 注册了 simsun 字体 然后就报这个错误 reportlab pdfbase ttfonts TTFError Not a recognized TrueType font version 0
  • thread_create 和 thread_resume

    在lk中我们一般通过thread create 来新建一个thread 但这个thread 是THREAD SUSPENDED 必须要调用thread resume 才能开始运行 enum thread state THREAD SUSPE
  • 城市内涝及桥洞隧道积水在线监测系统

    一 方案概述 近几年 全国频频爆发暴雨等极端天气 这对社会管理 城市运行和人民群众生产生活造成了巨大影响 加之部分城市排水防涝等基础设施建设滞后 调蓄雨洪和应急管理能力不足 出现了严重的暴雨内涝灾害 城市中的隧道和立交桥等低洼路段在遭遇短时
  • YOLOv3使用笔记——Kmeans聚类计算anchor boxes

    anchor boxes用来预测bounding box faster rcnn中用128 128 256 256 512 512 分三个尺度变换1 1 1 2 2 1 共计9个anchor来预测框 每个anchor预测2000个框左右 使
  • qedl中的fixDepth()简化

    如果将PerspectiveMode的设置为1 则会传递zNear和Zfar 在fixDepth 中 而将perspectiveMode 0 则大大简化fixDepth float fixDepth float depth return c
  • 贷款预测问题(探索性分析+多种解决方案)

    用到的数据集 train 链接 https pan baidu com s 1hCQKvLYxTb5MkltJDa1QlQ 提取码 jsh8 test 链接 https pan baidu com s 16SkJ7fo1yEutv4CwnW
  • 工厂方法(Factory Method):对象创建型模式

    文章目录 1 代码示例 2 工厂方法模式的定义 实现意图 1 代码示例 工厂方法模式 简称工厂模式或者多态工厂模式 与简单工厂模式相比 引入了更多的新类 灵活性更强 实现也更加复杂 符合开闭原则 付出的代价是需要新增加多个新的工厂类 如下