设计模式大白话——工厂模式

news2024/11/25 18:50:03

文章目录

  • 设计模式大白话——工厂模式
      • 1.1、简单工厂:
      • 1.2、工厂方法
      • 1.3、抽象工厂

设计模式大白话——工厂模式

1.1、简单工厂:

  • 场景与思路

    ​ 现在需要开一个 Pizza 店,Pizza 店可以生产各种口味的 Pizza

    ​ 既然要生产各种各样的 Pizza,那就会很容易想到要对 Pizza 进行抽象,这个时候我们只需要创建一个 PizzaStore 专门去用于生产即可。

  • 示例代码:

    package main
    
    // Pizza 产品的抽象
    type Pizza interface {
    	GetName() string
    }
    
    type NYPizza struct {
    	Name string
    }
    
    func (p NYPizza) GetName() string {
    	return p.Name
    }
    
    type ChicagoPizza struct {
    	Name string
    }
    
    func (p ChicagoPizza) GetName() string {
    	return p.Name
    }
    
    type PizzaStore struct {
    }
    
    func (ps PizzaStore) OrderPizza(t string) Pizza {
    	// 生产不同口味的披萨
    	if t == "Cheese" {
    		// 芝士味
    		return NYPizza{Name: "Cheese Pizza"}
    	} else if t == "Chocolate" {
    		// 巧克力味
    		return ChicagoPizza{Name: "Chocolate Pizza"}
    	}
    
    	return nil
    }
    
    func main() {
    	pizzaStore := PizzaStore{}
    
    	println(pizzaStore.OrderPizza("Cheese").GetName())    // Cheese Pizza
    	println(pizzaStore.OrderPizza("Chocolate").GetName()) // Chocolate Pizza
    }
    
  • 分析

    简单工厂更像是一个编程习惯,对要生产的各种各样的产品进行了抽象

    在这里插入图片描述

1.2、工厂方法

  • 场景与思路

    ​ 现在,我们披萨店铺的规模不断地变大,准备在其他几个地区开分店,不同地区的口味都不一样,这个时候你会发现,上面的方法就不太适用了。
    ​ 简单梳理一下,这次相对于之前的变化是:多了很多店铺,我们可以对店铺进行抽象,这个时候不同的店铺子类只需要去实现各自的简单工厂即可!

  • 示例代码

    package main
    
    // Pizza 产品的抽象
    type Pizza interface {
    	GetName() string
    }
    
    type NYPizza struct {
    	name string
    }
    
    func (p NYPizza) GetName() string {
    	return p.name
    }
    
    type ChicagoPizza struct {
    	name string
    }
    
    func (p ChicagoPizza) GetName() string {
    	return p.name
    }
    
    // PizzaStore 创建者的抽象
    type PizzaStore interface {
    	OrderPizza(t string) Pizza
    }
    
    type NYPizzaStore struct {
    }
    
    func (s NYPizzaStore) OrderPizza(t string) Pizza {
    	if t == "1" {
    		return NYPizza{name: "NY 1"}
    	}
    	return NYPizza{name: "NY 2"}
    }
    
    type ChicagoPizzaStore struct {
    }
    
    func (s ChicagoPizzaStore) OrderPizza(t string) Pizza {
    	if t == "1" {
    		return ChicagoPizza{name: "Chicago 1"}
    	}
    	return ChicagoPizza{name: "Chicago 2"}
    }
    
    func main() {
    	NYPizzaStore := NYPizzaStore{}
    	println(NYPizzaStore.OrderPizza("1").GetName()) // NY 1
    
    	ChicagoPizzaStore := ChicagoPizzaStore{}
    	println(ChicagoPizzaStore.OrderPizza("1").GetName()) // Chicago 1
    }
    
  • 分析

    ​ 工厂方法模式里,对 Pizza产品)和 PizzaStore生产者)都进行了抽象,这样以来不同的店铺生产的披萨的方法都可以是不一样的,灵活性好,也好拓展。为了方便理解,我这里放上一个图片:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8k9OtarD-1689644400477)(/Users/fr.he/Library/Application Support/typora-user-images/image-20230714085747187.png)]

  • 模式定义
    工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把示例化推迟到子类。

    值得注意的是:这里所谓的的“决定”,并不是指子类运行时做决定,而是指在编写创建者类时,不需要制定实际创建的产品时哪一个。因为你选择了什么样的创建者,自然也就决定了创建什么样的产品。

1.3、抽象工厂

  • 场景与思路

    ​ 现在又有新的变化了!每个分店位于不同的城市,因此制作披萨的原料也是不一样的,因此生产出来的同类型的披萨也是有差别的,例如:面团和芝士。

    ​ 因为每个城市的原料各不相同,因此我们抽象了一个原料工厂接口,此接口用于获取面团和奶酪。此外,面团和奶酪也需要进行抽象。如下所示:

    // PizzaIngredientFactory 披萨原料工厂的抽象
    type PizzaIngredientFactory interface {
    	CreateDough() Dough
    	CreateCheese() Cheese
    	// 其他原料...
    }
    
    // Dough 面团接口
    type Dough interface {
    	GetName() string
    }
    
    // Cheese 芝士接口
    type Cheese interface {
    	GetName() string
    }
    

    ​ 具备如上接口之后,不同地区的披萨的只需要实现各自的方法即可。现在制作披萨的方式也与之前有所不同,披萨的制作现在依赖于原料工厂,如下所示:

    // Pizza 生产的披萨
    type Pizza struct {
    	factory PizzaIngredientFactory
    }
    
    func (p Pizza) Prepare() {
    	fmt.Printf("正在使用 %s 酱料和 %s 芝士准备披萨\n", p.factory.CreateDough().GetName(), p.factory.CreateCheese().GetName())
    	// 此处省略了具体的制作过程
    }
    

  • 示例代码

    package main
    
    import "fmt"
    
    // Pizza 生产的披萨
    type Pizza struct {
    	factory PizzaIngredientFactory
    }
    
    func (p Pizza) Prepare() {
    	fmt.Printf("正在使用 %s 酱料和 %s 芝士准备披萨\n", p.factory.CreateDough().GetName(), p.factory.CreateCheese().GetName())
    	// 此处省略了具体的制作过程
    }
    
    // PizzaIngredientFactory 披萨原料工厂的抽象
    type PizzaIngredientFactory interface {
    	CreateDough() Dough
    	CreateCheese() Cheese
    	// 其他原料...
    }
    
    // Dough 面团接口
    type Dough interface {
    	GetName() string
    }
    
    // NYDough 纽约面团
    type NYDough struct {
    }
    
    func (d NYDough) GetName() string {
    	return "NY Dough"
    }
    
    // ChicagoDough 芝加哥面团
    type ChicagoDough struct {
    }
    
    func (d ChicagoDough) GetName() string {
    	return "Chicago Dough"
    }
    
    // Cheese 芝士接口
    type Cheese interface {
    	GetName() string
    }
    
    // NYCheese 纽约芝士
    type NYCheese struct {
    }
    
    func (c NYCheese) GetName() string {
    	return "NY Cheese"
    }
    
    // ChicagoCheese 芝加哥芝士
    type ChicagoCheese struct {
    }
    
    func (c ChicagoCheese) GetName() string {
    	return "Chicago Cheese"
    }
    
    // NYPizzaIngredientFactory 纽约披萨原料工厂
    type NYPizzaIngredientFactory struct {
    }
    
    func (f NYPizzaIngredientFactory) CreateDough() Dough {
    	return NYDough{}
    }
    
    func (f NYPizzaIngredientFactory) CreateCheese() Cheese {
    	return NYCheese{}
    }
    
    // ChicagoPizzaIngredientFactory 芝加哥披萨原料工厂
    type ChicagoPizzaIngredientFactory struct {
    }
    
    func (f ChicagoPizzaIngredientFactory) CreateDough() Dough {
    	return ChicagoDough{}
    }
    
    func (f ChicagoPizzaIngredientFactory) CreateCheese() Cheese {
    	return ChicagoCheese{}
    }
    
    func main() {
    	NYPizza := Pizza{factory: NYPizzaIngredientFactory{}}
    	NYPizza.Prepare() // 正在使用 NY Dough 酱料和 NY Cheese 芝士准备披萨
    
    	ChicagoPizza := Pizza{factory: ChicagoPizzaIngredientFactory{}}
    	ChicagoPizza.Prepare() // 正在使用 Chicago Dough 酱料和 Chicago Cheese 芝士准备披萨
    }
    
  • 分析

    为了方便理解,可以参考如下的图片去理解

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kAfbD9Fb-1689644400478)()]

  • 模式定义

    抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确制定与体类。(说人话就是接口中定义了一组方法用于创建各种对象,可以结合上图去理解)

    如果你细心观察的话,会发现,抽象工厂模式的每个方法其实使用的都是工厂方法

最后,感谢你看到了这里。如果此文章有说的不对的地方,也欢迎纠正。

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

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

相关文章

管理类联考——英语——趣味篇——不择手段——d开头单词

🏠个人主页:fo安方的博客✨ 💂个人简历:大家好,我是fo安方,考取过HCIE Cloud Computing、CCIE Security、CISP、RHCE、CCNP RS、PEST 3等证书。🐳 💕兴趣爱好:b站天天刷&…

SignalTap II 软件使用步骤

文章目录 前言一、SignalTap II是什么?二、使用步骤三、总结四、参考资料 前言 环境: 1、Quartus18.1 2、板子型号:原子哥开拓者2(EP4CE10F17C8) 要求: 能够使用SignalTap II进行片上调试。 一、SignalTap II是什么? S…

海外媒体发稿:链游媒体发稿写作方法及优缺点解析

链游媒体发稿是一种新的媒体发布机制,它可以把信息准确、及时、有效地传播给大量的人,帮助企业实现信息的最大化传播,因此越来越多的公司也开始使用链游媒体发稿服务,本文就介绍链游媒体发稿写作的方法及小技巧。 一、链游媒体发稿…

Kubernetes Service的过程

文章目录 Kubernetes Service的实现基础内容1. 命令 ip route show table all2. DNAT3. IPVS和iptables4. Service Service的实现简述 Kubernetes Service的实现 基础内容 在了解Service之前,需要先了解一些额外的知识: 命令: ip route show table allDNATIPVS和iptables基础…

MNE脑电数据预处理

MNE 官网链接 导包 import mne import matplotlib.pyplot as plt加载数据集 不同格式数据集使用的函数不同,具体在官网搜索 raw mne.io.read_raw_brainvision(r"test.vhdr", preloadTrue)此语句为了画图方便 %matplotlib降采样 raw.resample(200)…

Vue3统计数值(Statistic)

可自定义设置以下属性: 数值的标题(title),类型:string | slot,默认:‘’数值的内容(value),类型:string | number,默认:…

MySql索引分类及创建索引的相关语法

1.索引分类 1.1 InnoDB中索引的分类 聚集索引与二级索引之间的B树的结构 sql语句索引执行的过程讲解 根据id查询的聚集索引效率要比二级索引高,故第一条sql的执行效率要高于第二条sql的执行效率。 2.索引语法 如果一个索引只关联一个字段,这种索引…

[虚幻引擎插件说明] DTOperateFile 使用蓝图操作文件

本插件可以在虚幻里面使用蓝图文件进行读、写、移动、复制、删除等操作。 目录 1. 节点说明 Get Stat Data – 获取文件信息 Directory Exists – 判断目录是否存在 Directory Create – 创建目录 Directory Delete – 删除目录 File Exists – 判断文件是否存在 File …

Kubernetes Dashboard部署安装

目录 Dashboard 官方文档:部署和访问 Kubernetes 仪表板(Dashboard) | Kubernetes 参考文档:(120条消息) K8S 安装 Dashboard_k8s 安装dashboard_tom.ma的博客-CSDN博客 扩展: K8S 安装 Dashboard 1、在 master …

BUFG/BUFGCE/BUFH/BUFHCE/BUFH/BUFGHCE/BUFMR/BUFMRCE/BUFR/IBUF/IBUFDS

本文对BUFG/BUFGCE/BUFH/BUFHCE简单介绍,便于后续查看。 原语的使用:在vivado中找到所要用的原语,直接将其实例化到设计中即可。 文章目录 BUFGBUFGCEBUFHBUFHCEBUFMRBUFRBUFMRCEIBUFIBUFDS 下图为 7 系列 FPGA 时钟架构图: BU…

TypeScript基础篇 - React Webpack TS 环境实战

目录 WebpackReactTS tsconfig.json src/App.tsx src/main.tsx scripts/webpack.config.js package.json scripts/template.html 一张ai生成图~ WebpackReactTS npm install react react-dom 【安装react并且安装一个react-dom】 引用时文件出现...;需要增加定义文件&a…

数据分析案例-数据分析师岗位招聘信息可视化

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

解决appium-doctor报ffmpeg cannot be found

一、下载ffmpeg安装包 https://ffmpeg.org/download.html 找到如图所示红框位置点击下载ffmpeg安装包。 二、配置ffmpeg环境变量 三、检查ffmpeg版本信息 重新管理员打开dos系统cmd命令提示符,输入ffmpeg查看是否出现版本信息,安装完好。 ffmpeg

在php中安装php_xlswriter扩展报错,找不到php_xlswriter.dll

前言:这里已经把下载的php_xlswriter.dll扩展放到了php安装目录的ext目录下,运行php -m还是报错找不到该扩展 原因:下载的扩展是nts的,而安装的php是ts的。查看当前php是nts还是ts: 在PHP中,可以利用phpin…

DWG文件怎么转图片?简单好用的转换方法分享

将CAD文件转换成图片的优势在于,图片文件更易于共享和传输。CAD文件通常比较大,而图片文件则更加轻便,容易通过电子邮件或者其他方式进行传输。此外,图片文件更易于浏览和查看。CAD文件需要特殊的软件才能打开和查看,而…

全志F1C200S嵌入式驱动开发(GPIO输出)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 和v3s一样,f1c200s本身的外部引脚比较少。所以这个时候,不可避免地,很多引脚的功能就会重叠在一起。这种情况下,我们就要学会取舍了。比如说,如果是学习sd卡的时候,那么spi的…

寻找下一个生成式AI独角兽,亚马逊云科技创业加速器火热来袭

生成式AI让人工智能技术又一次破圈,带来了机器学习被大规模采用的历史转折点。它正在掀起新一轮的科技革命,为人类带来前所未有的颠覆性的影响,而诸多创业者也应势而上,寻求创新机遇。生成式AI可以创造全新的客户体验、提高企业内…

QPainter中坐标系变换问题

一、坐标系简介。 Qt中每一个窗口都有一个坐标系,默认的,窗口左上角为坐标原点,然后水平向右依次增大,水平向左依次减小,垂直向下依次增大,垂直向上依次减小。原点即为(0,0&#xf…

【Jenkins】Jenkins构建前端流水线

目录 一、前言二、新建前端流水线1、点击新建任务2、填写流水线名称(这里我选择的是自由风格的软件项目),任务名称一般格式为:项目名称-前后端3、创建成功后的结果 三、配置前端流水线1、进入刚创建好的任务页面中,点击…

攻击载荷、木马、蠕虫、感染型病毒,你了解多少?

恶意程序是指数字世界中带有攻击意图的程序实体,通常可以分为攻击载荷、木马、蠕虫、感染型病毒。 1.攻击载荷 攻击载荷是指攻击者发起初始攻击并建立网络连接的武器载体,按照功能可以分为投递攻击类、连接控制类、独立攻击类。 投递攻击类有远程攻击类…