c++设计模式三:工厂模式

news2024/11/25 2:29:49

        本文通过一个例子简单介绍简单工厂模式、工厂模式和抽象工厂模式。

1.简单工厂(静态)

        假如我想换个手机,换什么手机呢?可以考虑苹果或者华为手机,那我们用简单工厂模式来实现这个功能:

        我们关注的产品是手机,那生产手机的工厂有苹果,有华为,用户也不确定选哪种怎么办?这里用简单工厂模式:定义两个枚举类型,然后写一个工厂类,根据用户传入的枚举类型生产对应品牌的手机:

手机基类:

#pragma once
class MyPhone
{
public:
	MyPhone(double price);
	~MyPhone();
	double getPrice() { return m_price; }
private:
	double m_price;
};
#include "MyPhone.h"

MyPhone::MyPhone(double price) :m_price(price)
{
}
MyPhone::~MyPhone()
{
}

苹果手机:

#pragma once
#include "MyPhone.h"
class Phone_Apple:public MyPhone
{
public:
	Phone_Apple(double price);
	~Phone_Apple();
};
#include "Phone_Apple.h"
#include "stdio.h"
Phone_Apple::Phone_Apple(double price):MyPhone(price)
{
	printf("This is iPhone!");
}
Phone_Apple::~Phone_Apple()
{
}

华为手机:

#pragma once
#include "MyPhone.h"

class Phone_Huawei :public MyPhone
{
public:
	Phone_Huawei(double price);
	~Phone_Huawei();
};
#include "Phone_Huawei.h"
#include "stdio.h"
Phone_Huawei::Phone_Huawei(double price) :MyPhone(price)
{
	printf("This is HUAWEI!");
}
Phone_Huawei::~Phone_Huawei()
{
}

简单工厂类:

#pragma once
#include "MyPhone.h"
enum phoneType
{
	APPLE_Phone,
	HUAWEI_Phone
};
class SimpleFactory
{
public:
	SimpleFactory();
	~SimpleFactory();

	MyPhone* createPhone(phoneType type);
};
#include "SimpleFactory.h"
#include "Phone_Apple.h"
#include "Phone_Huawei.h"
SimpleFactory::SimpleFactory()
{
	
}
SimpleFactory::~SimpleFactory()
{
}
MyPhone* SimpleFactory::createPhone(phoneType type)
{
	MyPhone* phone = nullptr;
	switch (type)
	{
	case APPLE_Phone:
		phone = new Phone_Apple(6000);
		break;
	case HUAWEI_Phone:
		phone = new Phone_Huawei(5600);
		break;
	}
	return phone;
}

用户根据自定义类型修改创建:

	SimpleFactory* factory = new SimpleFactory();
	//用户指定要苹果
	MyPhone* phone = factory->createPhone(APPLE_Phone);
	cout << "Price: " << phone->getPrice() << endl;

    delete phone;
	delete factory;

2.工厂模式        

        这里的工厂类似于一个手机销售店,你需要什么手机就提供什么手机,没有问题,如果用户增加了需求,想要添加三星、OPPO等,怎么办?

  1. 可以分别继承Myphone类,分别实现不同产品;
  2. 在SimpleFactory类中添加对应类别;
  3. 在createPhone方法中添加对应类别(还要引入对应的新的类和头文件);
  4. 可通过配置文件等方式准备好已有的类型供用户选择调用;

        很明显每次都要对原文件修改,如何避免呢?这里进入工厂模式:将生产手机的工厂抽象出来,然后将具体的生产厂家继承自这个抽象工厂,分别创建自己的产品:

抽象工厂类:

#pragma once
#include "MyPhone.h"
class IFactory
{
public:
	IFactory();
	~IFactory();

	virtual MyPhone* createPhone() = 0;
};

华为工厂:

#pragma once
#include "IFactory.h"
#include "MyPhone.h"
class HuaweiFactory : public IFactory
{
public:
	HuaweiFactory();
	~HuaweiFactory();
	virtual MyPhone* createPhone();
};
#include "HuaweiFactory.h"
#include "Phone_Huawei.h"
HuaweiFactory::HuaweiFactory()
{
}
HuaweiFactory::~HuaweiFactory()
{
}
MyPhone* HuaweiFactory::createPhone()
{
	MyPhone* phone = new Phone_Huawei(5600);
	return phone;
}

苹果工厂:

#pragma once
#include "IFactory.h"
#include "MyPhone.h"
class IphoneFactory :	public IFactory
{
public:
	IphoneFactory();
	~IphoneFactory();
	virtual MyPhone* createPhone();
};
#include "IphoneFactory.h"
#include "Phone_Apple.h"
IphoneFactory::IphoneFactory()
{
}
IphoneFactory::~IphoneFactory()
{
}
MyPhone* IphoneFactory::createPhone()
{
	MyPhone* phone = new Phone_Apple(6000);
	return phone;
}
	//3.2 工厂模式
	IFactory* factory = new IphoneFactory();
	MyPhone* phone = factory->createPhone();
	cout << "Price: " << phone->getPrice() << endl;

	IFactory* factory1 = new HuaweiFactory();
	MyPhone* phone1 = factory1->createPhone();
	cout << "Price: " << phone1->getPrice() << endl;

	delete phone;
	delete phone1;
	delete factory;
	delete factory1;

 3.抽象工厂模式

        这时,如果用户需要增加产品类型,比如华为的平板、苹果的平板怎么办?这就要引入抽象工厂模式了。 

  1. 将产品类进行抽象(这里可能会涉及多种产品);
  2. 写出具体的产品类;
  3. 将工厂类进行抽象;
  4. 具体工厂生产对应的产品(一个工厂可以生产自己品牌的多种产品)

 在原来代码基础上进行修改:

产品抽象类:

#pragma once
class MyPhone
{
public:
	MyPhone(double price);
	~MyPhone();
	double getPrice() { return m_price; }
private:
	double m_price;
};

class MyPad
{
public:
	MyPad(double price);
	~MyPad();
	double getPrice() { return m_price; }
private:
	double m_price;
};

苹果产品类:

#pragma once
#include "MyPhone.h"
class Phone_Apple:public MyPhone
{
public:
	Phone_Apple(double price);
	~Phone_Apple();
};
class Pad_Apple :public MyPad
{
public:
	Pad_Apple(double price);
	~Pad_Apple();
};

华为产品类:

#pragma once
#include "MyPhone.h"

class Phone_Huawei :public MyPhone
{
public:
	Phone_Huawei(double price);
	~Phone_Huawei();
};
class Pad_Huawei :public MyPad
{
public:
	Pad_Huawei(double price);
	~Pad_Huawei();
};

抽象工厂类:

#pragma once
#include "MyPhone.h"
class IFactory
{
public:
	IFactory();
	~IFactory();

	virtual MyPhone* createPhone() = 0;
	virtual MyPad* createPad() = 0;
}

具体工厂类:

#pragma once
#include "IFactory.h"
#include "MyPhone.h"
#include "Phone_Apple.h"
class IphoneFactory :	public IFactory
{
public:
	IphoneFactory();
	~IphoneFactory();
	virtual MyPhone* createPhone(){
		MyPhone* phone = new Phone_Apple(6000);
		return phone;
	}
	virtual MyPad* createPad() {
		MyPad* phone = new Pad_Apple(4900);
		return phone;
	}
};
#pragma once
#include "IFactory.h"
#include "MyPhone.h"
#include "Phone_Huawei.h"
class HuaweiFactory : public IFactory
{
public:
	HuaweiFactory();
	~HuaweiFactory();
	virtual MyPhone* createPhone() {
		MyPhone* phone = new Phone_Huawei(5600);
		return phone;
	}
	virtual MyPad* createPad() {
		MyPad* phone = new Pad_Huawei(4600);
		return phone;
	}
};

调用:

	//3.3 抽象工厂模式
	IFactory* factory = new HuaweiFactory();
	MyPad* pad = factory->createPad();
	cout << "Price: " << pad->getPrice() << endl;
	MyPhone* phone = factory->createPhone();
	cout << "Price: " << phone->getPrice() << endl;
	delete pad;
	delete phone;
	delete factory;

4.总结对比

 三种方法使用选择:

        分别理解三种模式并不困难,关键就在于根据实际问题实际情况选用不同的模式,先总结如下思考方式,供参考:

  •         当产品类型固定时可选择简单工厂模式(这里可以认为是零维的,即不用考虑其他维度);
  •         当产品涉及到不同厂商时,将工厂抽象化,不同厂商实现大厂的接口(这里可以认为是一维的,除了产品自身还需考虑厂商问题);
  •         当涉及到不同厂商的不同产品时,将工厂和产品分别抽象化(这里可以认为是二维的,考虑产品的种类以及厂商问题);

 总之要尽量满足OOP七大原则:

  • 开闭原则: 一个软件的实体应当对扩展开放,对修改关闭
  • 依赖倒转原则: 要针对接口编程,不要针对实现编程
  • 迪米特法则:只与你直接的朋友通信,而避免和陌生人通信

   三种方式的对比:

简单(静态)工厂模式:

        用来生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有代码;

工厂方法模式:

        用来生产同一等级结构中的固定产品(支持增加任意产品)

        优点:

  • 你可以避免创建者和具体产品之间的紧密耦合。
  • 单一职责原则。你可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护。
  • 开闭原则。无需更改现有客户端代码,你就可以在程序中引入新的产品类型。

      缺点:

  • 应用工厂方法模式需要引入许多新的子类,代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

抽象工厂模式:

         围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。

        优点:

  • 应用工厂方法模式需要引入许多新的子类,代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

        缺点:

  •   由于采用该模式需要向应用中引入众多接口和类,代码可能会比之前更加复杂。

参考文献:【精选】设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)_简单工厂模式 抽象工厂模式-CSDN博客1. 工厂方法模式(Factory Method) (yuque.com)2. 抽象工厂模式(Abstract Factory) (yuque.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1147390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能与航天技术的融合:未来发展的新趋势

人工智能与航天技术的融合&#xff1a;未来发展的新趋势 随着科技的飞速发展&#xff0c;人工智能和航天技术已经成为人类探索未知世界的重要工具。本文将探讨这两个领域的结合点&#xff0c;以及未来的发展趋势和应用前景。通过了解这些技术&#xff0c;读者将更好地理解人工…

用Python定义一个函数,用递归的方式模拟汉诺塔问题

【任务需求】 定义一个函数&#xff0c;用递归的方式模拟汉诺塔问题&#xff0c;三个柱子&#xff0c;分别为A、B、C&#xff0c;其中A柱子上有N个盘子&#xff0c;从小到大编号为1到N&#xff0c;盘子大小不同。现在要将这N个盘子从A柱子移动到C柱子上&#xff0c;但移动的过…

段页式管理方式

一、分段、分页的优缺点 1.分页管理&#xff1a;内存空间利用率高&#xff0c;无外部碎片&#xff0c;只有少量页内碎片&#xff0c;以物理结构划分&#xff0c;不便于按逻辑方式实现信息共享和保护 2.分段管理&#xff1a;为段长过大分配连续空间会很不方便&#xff0c;会产生…

Nginx动静分离以及防盗链问题

目录 1.动静分离 1.1概念 1.2准备环境 1.3.测试访问 2.Nginx防盗链问题 2.1nginx 防止网站资源被盗用模块 2.2防盗链配置 2.3准备两台机器 2.4测试 ①开启防盗链 ②让盗链ip可一访问服务资源 ③防盗链不设置none参数 1.动静分离 1.1概念 为了加快网站的解析速度&…

【图像分类】钢轨表面缺陷分类数据集介绍(4个类别)

写在前面&#xff1a; 首先感谢兄弟们的支持&#xff0c;让我有创作的动力&#xff0c;在创作过程我会尽最大能力&#xff0c;保证作品的质量&#xff0c;如果有问题&#xff0c;可以私信我&#xff0c;让我们携手共进&#xff0c;共创辉煌。 路虽远&#xff0c;行则将至&#…

Pytorch入门实例

数据集是受教育年限和收入,如下图 代码如下 import torch import numpy as np import matplotlib.pyplot as plt import pandas as pd import torch.nn as nn import torch.optim as optimdata pd.read_csv(./Income.csv)X torch.from_numpy(data.Education.values.reshape…

Windows环境下MosQuitto服务器搭建,安装mqtt服务端软件

1、下载、安装MosQuitto服务器 下载地址&#xff1a;http://mosquitto.org/files/binary/ 根据平台选择相应的代码下载。 安装完成后&#xff0c;安装文件夹下部分文件的功能

私有云:【9】Connection配置

私有云&#xff1a;【9】Connection配置 1、关闭IE增强配置2、Connection配置2.1、登录connection管理台配置许可证2.2、添加VCenter主机2.3、配置Composer 1、关闭IE增强配置 关闭此项 全部关闭 2、Connection配置 2.1、登录connection管理台配置许可证 上一章connection…

DevChat:你的私人助理,让工作变得如此简单!

前言&#xff1a; 首先我们来浅浅说下AI吧。有小伙伴把AI看得十分“高高在上”&#xff0c;觉得它属于“诸神之战”&#xff0c;与我等凡人无关。其实这个看法是不对的。就好像我们刚开始对于手机系统或者电脑系统感觉很有陌生感一样&#xff0c;一直到技术落地到抖音、微信等…

复习Animate和木疙瘩学习笔记-动画制作的回家之路

这个融媒体H5制作平台功能比较完善&#xff1a;包含了Flash(现在叫Animate)传统H5网页制作 720全景视频制作发布网页&#xff01; 主要功能&#xff1a;素材导入、2D动画制作、常见交互添加、发布生成链接二维码 基本就是一个制作H5为主&#xff0c;但是里面的动画可以依赖4种…

LeetCode 415 字符串相加 简单

题目 - 点击直达 1. 415 字符串相加 简单1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 415 字符串相加 简单 1. 题目详情 给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。…

[Java/力扣100]判断两棵二叉树是否相同

我希望通过这道题&#xff0c;能进一步了解递归思想和“树是递归定义的”这句话 分析 我们的目的是写一个方法来检验两棵树是否相同 什么叫“两棵树相同”&#xff1f;——相同的位置存在相同的结点 有三种情况&#xff1a;1、两棵树一颗为空一颗不为空——不相同&#xff…

高阶数据结构学习 —— 图(2)

文章目录 1、BFS1、DFS 1、BFS 广度优先。确定从哪个点开始&#xff0c;然后用队列来完成遍历。拿出一个点就把和这个点相连的其它点放进去&#xff0c;但是这样前面放进过队列的也有可能被再次放入&#xff0c;所以需要做好标记。一个队列&#xff0c;一个标记容器。在邻接矩…

NodeMCU ESP8266 面包板的介绍和使用详解(图文并茂)

文章目录 前言什么是面包&#xff1f;面包板的历史 如何使用&#xff1f;1 如何连接面包板2 如何读取面包板的行和列&#xff1f;面包板标签“”和“-”符号 3 电源轨连接4. 中心槽&#xff08;DIP 支持&#xff09; 实际案例总结 前言 在嵌入式学习的过程中&#xff0c;会遇到…

【ESP 保姆级教程】疯狂TFT篇 ——教你从0到1打造太空人时钟① TFT_eSPI、TJpg_Decoder库

系列最终效果,一步步进阶学习 忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-10-27❤️❤️ 本篇更新记录 2023-10-27❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝🙏 此博客均由博主单独编写,不存在任何…

mathtype7.4破解永久激活码

MathType(数学公式编辑器)是由Design Science公司研发的一款专业的数学公式编辑工具。MathType功能非常强大&#xff0c;尤其适用于专门研究数学领域的人群使用。使用MathType让你在输入数学公式的时候能够更加的得心应手&#xff0c;各种复杂的运算符号也不在话下。 MathType最…

Android开发知识学习——登录和第三方授权

文章目录 学习资源来自&#xff1a;扔物线登录和授权的区别HTTP 中确认授权&#xff08;或登录&#xff09;的两种方式CookieAuthorization主流用法&#xff1a;Basic主流用法&#xff1a;Bearer&#xff1a;OAuth2 的流程&#xff1a;第三方 App 通过微信登录的流程Refresh to…

问题 A: 数塔(dp算法)

算法分析&#xff1a; 1.创建两个数组&#xff0c;一用作输入&#xff08;下层&#xff09;&#xff0c;一用于复制&#xff08;上层&#xff09; &#xff08;1&#xff09;第一层时&#xff0c;直接输入进temp数组 &#xff08;2&#xff09;大于第一层&#xff0c;输入arr…

英语兔语法笔记(1)动词分类+动词时态

B站英语兔的语法课&#xff0c;强推&#xff01;和学校里面的不同&#xff0c;通俗易懂&#xff0c;看过之后真的醍醐灌顶~ 英语兔语法网课https://www.bilibili.com/video/BV1XY411J7aG?p1&vd_source1d1be06bfa4daa398bc518a66de92cf8 一.动词分类 大致看一下就好&…

深度神经网络的数学原理:基于超平面、半空间与线性区域的表示

概述 以前的文章主要描述了神经网络&#xff0c;即多层感知机、全连接模型的运行原理&#xff0c;还是以实验为主&#xff0c;数学描述为辅的方式&#xff0c;这篇文章以纯数学的视角来描述神经网络的运行原理&#xff0c;主要以前馈过程为主&#xff08;反向传播的动力学过程…