设计模式:工厂方法模式(讲故事图文易懂)

目录

  • 简单工厂
  • 工厂方法模式


简单工厂

定义:简单工厂由一个工厂根据参数类型决定创建哪种产品的实例。
简单工厂不包含在23种设计模式之内(简单工厂不满足开闭原则,后面会详细讲)
举例:张三去4S店买了车,显而易见,车不是张三造出来的,车是工厂造出来的,张三获得了该车并能够使用该车,但是造车的细节张三不用知道。

铁蛋在一家汽车工厂上班,这家工厂承接了”小米汽车“和”华为汽车“的生产,一天铁蛋接到了要求,要新开一个”长安汽车“生产线生产长安汽车,铁蛋要怎么做呢?
在这里插入图片描述

先写一个简单工厂的例子,再看看铁蛋要怎么做?
简单工厂模式有三个角色:抽象基类(Car)
                                            实现类(XiaoMiCar、HuaWeiCar)
                                            简单工厂类(SimpleFactory)

#include <iostream>
#include <string>
using namespace std;

//抽象基类
class Car
{
public:
	Car(string name) : name_(name) {}
	virtual void Show() = 0;

protected:
	string name_;
};

//实现类
class XiaomiCar : public Car {
public:
	XiaomiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆小米轿车: " << name_ << endl;
	}
};
//实现类
class HuaweiCar : public Car {
public:
	HuaweiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆华为轿车: " << name_ << endl;
	}
};

enum CarType
{
	XIAOMI, HUAWEI
};

//简单工厂类
class SimpleFactory {
public:
	Car* CreateCar(CarType type) {
		switch (type) {
		case XIAOMI:
			return new XiaomiCar("SU7");
		case HUAWEI:
			return new HuaweiCar("问界");
		default:
			return nullptr;
		}
	}
};

int main()
{
	SimpleFactory* factory = new SimpleFactory();
	Car* c1 = factory->CreateCar(XIAOMI);
	Car* c2 = factory->CreateCar(HUAWEI);
	c1->Show();
	c2->Show();

	delete c1;
	delete c2;
	delete factory;
}

运行结果:
在这里插入图片描述
上面小米汽车XiaomiCar 和华为汽车HuaweiCar 继承了汽车基类Car。
简单工厂SimpleFactory根据传入不同类型CarType来生产不同类型的车。

你是否想到了铁蛋要怎么做,铁蛋是这样做的:
1.增加长安汽车类(继承了汽车基类Car)
2.修改简单工厂类SimpleFactory(增加”CHANGAN“类型车的创建)

#include <iostream>
#include <string>
using namespace std;

class Car
{
public:
	Car(string name) : name_(name) {}
	virtual void Show() = 0;

protected:
	string name_;
};

class XiaomiCar : public Car {
public:
	XiaomiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆小米轿车: " << name_ << endl;
	}
};

class HuaweiCar : public Car {
public:
	HuaweiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆华为轿车: " << name_ << endl;
	}
};

class ChanganCar : public Car {
public:
	ChanganCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆长安轿车: " << name_ << endl;
	}
};

enum CarType
{
	XIAOMI, HUAWEI, CHANGAN
};

class SimpleFactory {
public:
	Car* CreateCar(CarType type) {
		switch (type) {
		case XIAOMI:
			return new XiaomiCar("SU7");
		case HUAWEI:
			return new HuaweiCar("问界");
		case CHANGAN:
			return new ChanganCar("深蓝《偷偷藏不住》");
		default:
			return nullptr;
		}
	}
};

int main()
{
	cout << "------简单工厂------" << endl;
	SimpleFactory* factory = new SimpleFactory();
	Car* c1 = factory->CreateCar(XIAOMI);
	Car* c2 = factory->CreateCar(HUAWEI);
	Car* c3 = factory->CreateCar(CHANGAN);
	c1->Show();
	c2->Show();
	c3->Show();

	delete c1;
	delete c2;
	delete c3;
	delete factory;
}

运行结果:
在这里插入图片描述
成功生产了长安轿车!


但是从逻辑上来讲,同一个工厂不会生产小米汽车又生产华为汽车,又或者这个工厂还将生产长安汽车

因为:当简单工厂想增加生产长安汽车时,会修改简单工厂类SimpleFactory(增加”CHANGAN“类型车的创建),违反了开闭原则(对修改关闭,对扩展开放)。每当我们增加一种产品的时候就要去修改工厂方法,这样会破坏其内聚性,给维护带来额外开支。

所以,有了工厂方法模式来解决该问题。

工厂方法模式

定义:工厂基类负责定义创建对象的公共接口,子类工厂负责创建出具体的对象,来实现不同产品的工厂化创建。
设计模式有三大分类:创建型模式、结构型模式、行为型模式
工厂方法模式属于创建型模式
在这里插入图片描述
工厂方法模式不只有一个工厂每个工厂只生产一种特定的产品。这样做的好处是当以后需要增加新的产品时,直接新增加一个对应的工厂就可以,而不是去修改原有的工厂,符合编程原则的开闭原则

#include <iostream>
#include <string>
using namespace std;

class Car
{
public:
	Car(string name) : name_(name) {}
	virtual void Show() = 0;

protected:
	string name_;
};

class XiaomiCar : public Car {
public:
	XiaomiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆小米轿车: " << name_ << endl;
	}
};

class HuaweiCar : public Car {
public:
	HuaweiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆华为轿车: " << name_ << endl;
	}
};

class Factory {
public:
	virtual Car* CreateCar(string name) = 0;
};

class XiaomiFactory : public Factory
{
public:
	Car* CreateCar(string name)
	{
		return new XiaomiCar(name);
	}
};

class HuaweiFactory : public Factory
{
public:
	Car* CreateCar(string name)
	{
		return new HuaweiCar(name);
	}
};

int main()
{
	cout << "------工厂方法模式------" << endl;
	Factory* xiaomiFactory = new XiaomiFactory();
	Factory* huaweiFactory = new HuaweiFactory();
	Car* xiaomiCar = xiaomiFactory->CreateCar("SU7");
	Car* huaweiCar = huaweiFactory->CreateCar("问界");

	xiaomiCar->Show();
	huaweiCar->Show();

	delete xiaomiCar;
	delete huaweiCar;
	delete xiaomiFactory;
	delete huaweiFactory;
}

运行结果:
在这里插入图片描述

同样上面小米汽车XiaomiCar 和华为汽车HuaweiCar 继承了汽车基类Car。
小米工厂XiaomiFactory和华为工厂HuaweiFactory继承了工厂基类Factory。
小米工厂生产小米汽车,华为工厂生产华为汽车。

这样,铁蛋想生产”长安汽车“,就直接新建长安汽车工厂,由长安工厂来生产长安汽车,这样就不用修改小米工厂和华为工厂,满足程序设计的开闭原则

铁蛋是这样做的
1.增加了长安汽车类ChanganCar (继承了汽车基类Car)
2.增加了长安汽车工厂ChanganFactory (继承了工厂基类Factory)

#include <iostream>
#include <string>
using namespace std;

class Car
{
public:
	Car(string name) : name_(name) {}
	virtual void Show() = 0;

protected:
	string name_;
};

class XiaomiCar : public Car {
public:
	XiaomiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆小米轿车: " << name_ << endl;
	}
};

class HuaweiCar : public Car {
public:
	HuaweiCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆华为轿车: " << name_ << endl;
	}
};

class Factory {
public:
	virtual Car* CreateCar(string name) = 0;
};

class XiaomiFactory : public Factory
{
public:
	Car* CreateCar(string name)
	{
		return new XiaomiCar(name);
	}
};

class HuaweiFactory : public Factory
{
public:
	Car* CreateCar(string name)
	{
		return new HuaweiCar(name);
	}
};

class ChanganCar : public Car {
public:
	ChanganCar(string name) : Car(name) {}
	void Show() {
		cout << "获得一辆长安轿车: " << name_ << endl;
	}
};

class ChanganFactory : public Factory
{
public:
	Car* CreateCar(string name)
	{
		return new ChanganCar(name);
	}
};

int main()
{
	cout << "------工厂方法模式------" << endl;
	Factory* xiaomiFactory = new XiaomiFactory();
	Factory* huaweiFactory = new HuaweiFactory();
	Factory* changanFactory = new ChanganFactory();
	Car* xiaomiCar = xiaomiFactory->CreateCar("SU7");
	Car* huaweiCar = huaweiFactory->CreateCar("问界");
	Car* changanCar = changanFactory->CreateCar("深蓝《偷偷藏不住》");

	xiaomiCar->Show();
	huaweiCar->Show();
	changanCar->Show();

	delete xiaomiCar;
	delete huaweiCar;
	delete changanCar;
	delete xiaomiFactory;
	delete huaweiFactory;
	delete changanFactory;
}

运行结果:
在这里插入图片描述


无广告,以汽车为例故事形式介绍了简单工厂和工厂方法模式。

谢谢观看,祝顺利!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

城市生态数据大屏,PSD设计稿

现分享生态系统可视化大数据大屏的 Photoshop 源文件&#xff0c;下载即用&#xff01;以下为截图示意。 若需 更多行业 相关的大屏&#xff0c;请移步小7的另一篇文章&#xff1a;200套精选数据可视化大屏&#xff0c;大屏PSD设计&#xff08;各行业大屏UI&#xff09;https:…

DevExpress 皮肤改变触发后触发的事件,用来保存皮肤配置

代码&#xff1a; private UserLookAndFeel userLookAndFeel; public MainGeneral() {InitializeComponent();// 创建 UserLookAndFeel 实例userLookAndFeel new UserLookAndFeel(this);// 订阅 StyleChanged 事件userLookAndFeel.StyleChanged UserLookAndFeel_StyleChange…

UDP套接字搭建简易服务器与客户端

使用UDP套接字搭建 文章目录 使用UDP套接字搭建前言一、基本结构二、使用步骤1.服务器端2.客户端 三、效果展示总结 前言 这次较上个版本《Python 网络编程之搭建简易服务器和客户端》https://only-me.blog.csdn.net/article/details/135251171增加了&#xff1a; UDP协议来进…

1.PHP简单入门

1.PHP代码执行方式 PHP是在服务器端执行&#xff0c;然后返回给用户结果。 如果直接使用浏览器打开&#xff0c;就会解析为文本。 意思是说&#xff0c;浏览器通过 http请求&#xff0c;才能够执行php页面。 2.PHP代码框架 开启本机服务器&#xff08;下载软件略&#xff09…

数据结构: 位图

位图 概念 用一个bit为来标识数据在不在 功能 节省空间快速查找一个数在不在一个集合中排序 去重求两个集合的交集,并集操作系统中的磁盘标记 简单实现 1.设计思想:一个bit位标识一个数据, 使用char(8bit位)集合来模拟 2.预备工作:a.计算这个数在第几个char b.是这个ch…

全球日光地图分布地图数据

日光地图分布地图数据 Daylight 是全球开放地图数据的完整分发版&#xff0c;可在社区和专业地图制作者的支持下免费获取。我们将 OpenStreetMap 等项目的全球贡献者的工作与日光制图合作伙伴的质量和一致性检查结合起来&#xff0c;创建免费、稳定且易于使用的街道比例全球地…

【K8S 部署】基于kubeadm搭建Kurbernetes集群

目录 一、基本架构 二、环境准备: 三、安装部署 1、所有节点安装docker 2、、所有节点安装kubeadm&#xff0c;kubelet和kubectl 3、配置网络--flannel 4、测试 pod 资源创建 四、安装部署与k8s集群对接的Harbor仓库 五、Dashboard安装部署&#xff1a; 一、基本架构…

基于单片机的语音识别自动避障小车(论文+源码)

1.系统设计 此次基于单片机的语音识别自动避障小车&#xff0c;以STC89C52单片机作为系统的主控制器&#xff0c;利用超声波模块来实现小车与障碍物距离的测量并通过LCD液晶显示&#xff0c;当距离低于阈值时会通过WT588语音模块进行报警提示&#xff0c;并且小车会后退来躲避…

微信小程序-父子页面传值

父子页面传值 父页面向子页面传值 方法一&#xff1a; 父页面&#xff1a; 1. /page/xxx/xxx?id1子页面&#xff1a; onLoad:function(option){ }方法二 <bindtap“func” data-xxx””> 子页面向父页面传值 定义父子页面 父页面&#xff1a;hotspot 子页面&a…

uni-app App.vue生命周期全局样式全局存储globalData

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

程序员必备的数据处理神器-瑞士军刀cyberchef

本文将介绍一款强大的工具&#xff0c;囊括了网络世界范围内绝大数据的编解码技术&#xff0c;加解密技术&#xff0c;数格式转换技术&#xff0c;并提供了编码和解码&#xff0c;加解密以及数据转换的方法方法。对于程序员&#xff0c;这一一款不可多得的神器&#xff0c;在也…

<Icon-ResizER>support

If you get any questions in using app, email me caohechunhotmail.com.

OPenGL GLSL

shji 数据类型 整型&#xff08;有符号/无符号&#xff09; 浮点数&#xff08;单精度&#xff09; 布尔值 向量类型/矩阵类型 bool bDone false int value 1; unint vale 21u float value 2.1 向量/分量类型 vec2,vec3,vec4 2分量 3 分量 4 分量复电向量 i…

深入了解小红书笔记详情API:为内容创新提供动力

一、小红书笔记详情API简介 小红书笔记详情API是一种允许开发者访问小红书平台上的笔记详细数据的接口。通过这个API&#xff0c;我们可以获取笔记的标题、内容、标签、点赞数、评论数等详细信息。这些数据对于内容创作者和品牌来说至关重要&#xff0c;可以帮助他们了解用户喜…

day13--JDK8~17新特性(上):

第18章_JDK8-17新特性&#xff08;上&#xff09; 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. Java版本迭代概述 1.1 发布特点&#xff08;小步快跑&#xff0c;快速迭代…

Java技术栈 —— Nginx的使用

Java技术栈 —— Nginx的使用 一、认识Nginx二、搭建Nginx环境2.1 在Ubuntu上安装Nginx 三、使用Nginx3.1 配置负载均衡(HTTP) 一、认识Nginx 企业需要运行多个相同的副本&#xff0c;并将负载分散在整个系统集群上&#xff0c;为了高性能的负载均衡&#xff0c;引入了Nginx代…

vue实现滑动切换:切换选项时滑块有滑动过渡的效果

效果图 思路&#xff1a; 1. 高亮的色块是独立的一个盒子&#xff0c;需要插入当前激活的内容用来撑开色块盒子的宽度&#xff0c;这样色块的宽度就会和当前激活的内容宽度一致&#xff0c;色块的字体颜色设置透明即可 2. 色块滑动的距离是读当前激活元素的offsetLeft&#x…

UG装配-接触对齐

UG装配约束命令在如下位置 首选接触&#xff1a;含接触和对齐&#xff0c;自动判断两种类型 接触&#xff1a;约束对象使其曲面法向在相反方向&#xff0c;并共面或共线 对齐&#xff1a;约束对象使其曲面法向在同一方向&#xff0c;并共面或共线 自动判断中心/轴&#xff1…

RK3568笔记七:yolov5-seg实例分割测试验证

若该文为原创文章&#xff0c;转载请注明原文出处。 记录的目的是想在RK3568上实现实例分割&#xff0c;在github的rknn_mode_zoo仓库里看到了例子&#xff0c;带着疑问测试了一下&#xff0c;结果跑通了&#xff0c;这里记录下全过程。 一、环境 1、硬件&#xff1a;正点原…

kafka 的零拷贝原理

文章目录 kafka 的零拷贝原理 今天来跟大家聊聊kafka的零拷贝原理是什么&#xff1f; kafka 的零拷贝原理 零拷贝是一种减少数据拷贝的机制&#xff0c;能够有效提升数据的效率&#xff1b;   在实际应用中&#xff0c;如果我们需要把磁盘中的某个文件内容发送到远程服务器上…