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

目录

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


简单工厂

定义:简单工厂由一个工厂根据参数类型决定创建哪种产品的实例。
简单工厂不包含在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;
}

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


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

谢谢观看,祝顺利!

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

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

相关文章

网页爬虫对于网络安全有哪些影响?

在当今信息爆炸的时代&#xff0c;网络已经成为人们获取信息、交流思想和开展业务的重要平台。然而&#xff0c;随着网络的普及和技术的不断发展&#xff0c;网络安全问题也日益凸显&#xff0c;其中网页爬虫对网络安全的影响不容忽视。本文将就网页爬虫对网络安全的影响进行深…

从不同应用,划片机主要包括如下几个方面

在半导体行业中&#xff0c;划片机被广泛应用于各种材料和应用的切割和加工。根据不同的应用&#xff0c;划片机主要可以分为以下几个方面&#xff1a; 一、半导体材料划片 半导体材料划片是划片机最早的应用领域之一。在这个领域中&#xff0c;划片机主要被用于将半导体材料&…

test ui-02-UI 测试组件之 Appium 入门介绍

Appium简介 正如主页所述&#xff0c;Appium的目标是支持许多不同平台&#xff08;移动、Web、桌面等&#xff09;的UI自动化。 不仅如此&#xff0c;它还旨在支持用不同语言&#xff08;JS、Java、Python等&#xff09;编写的自动化代码。 将所有这些功能组合到一个程序中是…

工程中uint8变量文件比uint32变量文件大4字节的问题排查

前言 &#xff08;1&#xff09;如果有嵌入式企业需要招聘湖南区域日常实习生&#xff0c;任何区域的暑假Linux驱动实习岗位&#xff0c;可C站直接私聊&#xff0c;或者邮件&#xff1a;zhangyixu02gmail.com&#xff0c;此消息至2025年1月1日前均有效 &#xff08;2&#xff0…

uniapp中组件库的Textarea 文本域的丰富使用方法

目录 #平台差异说明 #基本使用 #字数统计 #自动增高 #禁用状态 #下划线模式 #格式化处理 API #List Props #Methods #List Events 文本域此组件满足了可能出现的表单信息补充&#xff0c;编辑等实际逻辑的功能&#xff0c;内置了字数校验等 注意&#xff1a; 由于…

金和OA SAP_B1Config.aspx存在未授权访问漏洞

产品简介 金和网络是专业信息化服务商&#xff0c;为城市监管部门提供了互联网监管解决方案&#xff0c;为企事业单位提供组织协同OA系统升开发平台&#xff0c;电子政务一体化平台智慧电商平合等服务 漏洞概述 金和OA SAP_B1Config.aspx存在未授权访问漏洞&#xff0c;攻击…

Jenkins的Transfers路径怎么配置,解决Transfers配置不生效的问题

Transfers配置: 1.配置Source files: 要填写jar包的相对路径,从当前项目工作空间的根目录开始,看看我的工作空间你就懂了 !如图 我填的是 parent/build/libs/parent-1.0.0.jar,即不要 fdw1/ 的前缀 2.配置Remote directory: 远程目标文件夹,也就是你jar包要放到远程…

【LeetCode】每日一题 2023_12_31 一年中的第几天(日期)

文章目录 随便聊聊时间题目&#xff1a;一年中的第几天题目描述代码与解题思路 随便聊聊时间 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 12 月的打卡勋章&#xff0c;get&#xff01; 题目&#xff1a;一年中的第几天 题目链接&#xff1a;1154. 一年中…

Nextjs打包类型检查报错ype error: Property ‘card_list‘ does not exist on type(已解决)

在Nextjs 中 在数组 map 的时候报错如下: 里面的数据类型是 data1 {cart_list:[]} 那么在 声明类型的时候 使用 data1:{card_list:any[]} export default function Card({authStates,data1,data2}:{authStates:boolean;data1:{card_list:any[]};data2:any[]}) {}) 这样就…

2024.1.3每日一题

LeetCode每日一题 2487.从链表中移除节点 2487. 从链表中移除节点 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个链表的头节点 head 。 移除每个右侧有一个更大数值的节点。 返回修改后链表的头节点 head 。 示例 1&#xff1a; 输入&#xff1a;head [5,…

设置代理IP地址对网络有什么影响?爬虫代理IP主要有哪些作用?

在互联网的广泛应用下&#xff0c;代理IP地址成为了一种常见的网络技术。代理IP地址可以改变用户的上网行为&#xff0c;进而影响网络访问的速度和安全性。本篇文章将探讨设置代理IP地址对网络的影响&#xff0c;以及爬虫代理IP的主要作用。 首先&#xff0c;让我们来了解一下代…

kafka容灾演练的方案

背景 kafka可以通过MirrorMaker工具把集群的数据从一个集群同步到另一个集群&#xff0c;通过在另一个数据中心创建灾备集群的方式可以做到容灾的效果,但是如果我们不通过如此重量级的工具也想达到容灾演练的目的&#xff0c;可以怎么做呢 kafka简单容灾实现 当原kafka集群发…

Allegro看不到PCB元件的丝印和装配层

#创作灵感# PCB板到处Gerber文件加工回来&#xff0c;板子上没有元件边框丝印&#xff0c;但是有元件编号。因为只是样板&#xff0c;影响不大&#xff0c;就没有当回事。直到发出去贴片&#xff0c;发送了钢网层和装配层&#xff0c;反馈说不知道元器件的极性。这就纳闷了&…

Android测试——(下篇)

Android测试&#xff08;五&#xff09;&#xff1a;Instrumented 单元测试 Instrumented 单元测试是在真机并且可以上运行的测试&#xff0c;它利用Android框架API和支持的API&#xff08;如Android测试支持库&#xff09;。如果你的测试需要访问工具信息&#xff08;例如目标…

STM32 学习(三)OLED 调试工具

目录 一、简介 二、使用方法 2.1 接线图 2.2 配置引脚 2.3 编写代码 三、Keil 工具调试 一、简介 在进行单片机开发时&#xff0c;有很多调试方法&#xff0c;如下图&#xff1a; 其中 OLED 就是一种比较好用的调试工具&#xff1a; OLED 硬件电路如下&#xff0c…

linux centos 部署 jenkins

一、试了用容器部署&#xff0c;不行。(建议别用容器部署) 二、直接部署在主机上 1、安装java环境 yum install java-11-openjdk-devel # 检查 java -version # 打印 [rootiZwz9a99mctbkabkh2imhdZ init.d] java -version openjdk version "11.0.21" 2023-10-17 L…

轻松上手:Postman Interceptor 插件使用指南

什么是 Postman&#xff1f; Postman 是一种用于测试和开发 API 的工具&#xff0c;让开发者可以轻松地构建、发送、调试 HTTP 请求&#xff0c;并检查响应结果。通过Postman&#xff0c;开发者可以在不编写代码的情况下快速测试 API 的正确性和可靠性。Postman 还支持协作和自…

Cesium加载大规模三维数据渲染性能优化方案

根据实际项目经验和近期的论文&#xff0c;总结一下Cesium加载大规模三维数据性能优化方法。个人认为在实际的GIS数字孪生项目中,其可行的优化手段主要有三种&#xff1a; &#xff08;1&#xff09;通过专业的转换工具CesiumLab等对原始的三维模型进行轻量化处理&#xff0c;包…

第4课 FFmpeg读取本地mp4文件并显示

在上节课&#xff0c;我们使用FFmpeg实现了一个最简单的rtmp播放器&#xff0c;它看起来工作正常。这节课&#xff0c;我们尝试让它来播放本地的mp4文件试试。 1.压缩备份上节课工程文件夹为demo3.rar&#xff0c;并修改工程文件夹demo3为demo4&#xff0c;重要的事情再说一遍…

rime中州韵小狼毫 Upper lua Filter 首字母大写滤镜

在 rime中州韵小狼毫 easyEnglish输入法 一文中&#xff0c; 我们定义了 easy-English 输入方案。输入效果如下&#x1f447;&#xff1a; 我们知道&#xff0c;在英文世界中&#xff0c;单词有首字母大写的习惯&#xff0c;如果我们输入 english 单词后&#xff0c;再回来改…