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

文章目录

  • 设计模式大白话——工厂模式
      • 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.mfbz.cn/a/38372.html

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

相关文章

在新建环境下配置低版本opencv

我这边是要解决 python报错:AttributeError: ‘module’ object has no attribute xfeatures2d’的问题, xfeatures2d在新版本已经被取消,但是需要使用老版本的一个函数 确定opencv与python的版本对应关系 一般来说可以对照这个表 具体来说…

【Spring】Spring更简单的读取和存储对象---使用注解

目录 1.Spring的存储对象------存储Bean对象 1.前置工作,配置扫描路径 2.添加注解存储Bean对象 1.Controller(控制器存储) 2.service(服务存储) 3.Repository(仓库存储) 4.Component&…

Java面试突击

Java面向对象有哪些特征,如何应用 ​ 面向对象编程是利用类和对象编程的一种思想。万物可归类,类是对于世界事物的高度抽象 ,不同的事物之间有不同的关系 ,一个类自身与外界的封装关系,一个父类和子类的继承关系&…

手动下载composer项目放在vendor目录下并加载

比如添加easywechat。 说是手动,其实半手动。 到GitHub或gitee下载 1、下载后放在项目根目录下的vendor文件夹 2、在项目根目录的文件composer.json文件添加一段 "autoload": {"psr-4": {"EasyWeChat\\": "vendor/overtrue/wech…

HCIP第一课实验小练习

目录 题目:​编辑 第一步:地址规划(子网划分) 第二步:设计拓扑并规划地址配置 第三步:VLAN规划配置 LW1 LW2 第四步:网关配置 第五步:及静态路由配置 第六步防止成环 题目&…

计算机视觉和滤帧技术

01 什么是计算机视觉 进入主题之前,先聊聊计算机视觉。 计算机视觉是指利用摄像头和电脑识别、跟踪和测量目标,并进行图像处理,使其适合人眼观察或仪器检测。作为一个科学学科,计算机视觉模拟生物视觉,旨在实现图像和视…

郭东白的架构课学习笔笔记(1)

1.架构师的品质 自信和勇气(正确的废话)拥有战略意图,所谓战略意图,就是拥有与其资源和能力极不相称的雄心壮志。使用演绎法寻找架构原理,而不是归纳法。 2.如何提升自己的架构能力 向身边比自己厉害的优秀架构师或…

【yarn】 ‘husky install‘ fails if ‘.git‘ directory does not exists解决方法

问题描述 环境:win10 yarn 1.22.19 问题:在使用yarn安装前端依赖时,yarn install 出现错误: .git can’t be found (see https://git.io/Jc3F9) error Command failed with exit code 1. 截图 原因分析 根据设计,husky安装必…

scala学习手册

1. case class学习 样例类模式匹配 1.1 样例类(case class)适合用于不可变的数据。它是一种特殊的类,能够被优化以用于模式匹配。 case class MetaData(userId: String)case class Book(name: String) {def printBookName(): Unit {printl…

Python读取excle文件,插入到数据库

一、需求背景 最近项目实践过程中遇到了一个问题:在使用Navicat将数据导入到PostgreSQL数据库时,发现时间格式的字段中的时间数值发生了变化,导致部分数据的时间不正确,故数据手动导入数据库报错。为了解决这个问题,决…

ARM中栈的种类与运用

1. 栈的概念 栈,本身是一段内存,程序运行时用于保存一些临时数据,如局部变量、参数、返回地址等等。 学习了数据结构,对栈的概念相信大家都不陌生,后进先出的数据结构,即最后进栈的元素最先出栈。但是在C语…

(学习笔记-TCP基础知识)TCP与UDP区别

UDP UDP不提供复杂的控制机制,利用IP提供面向[无连接]的通信服务。 UDP协议非常简单,头部只有8个字节(位),UDP的头部格式如下: 目标和源端口:主要是告诉UDP协议应该把报文发给哪个进程包长度:该字段保存了…

【码银送书第二期】《高并发架构实战:从需求分析到系统设计》

很多软件工程师的职业规划是成为架构师,但是要成为架构师很多时候要求先有架构设计经验,而不做架构师又怎么会有架构设计经验呢?那么要如何获得架构设计经验呢? 一方面可以通过工作来学习,观察所在团队的架构师是如何…

栈和队列【数据结构】

1、栈 &#xff08;1&#xff09;Stack.h #pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <stdbool.h>typedef int STDataType;typedef struct Stack {STDataType* a;int top;int capacity; }ST;void STInit(ST*…

设计模式——桥梁模式

桥梁模式 定义 桥梁模式&#xff08;Bridge Pattern&#xff09;也叫做桥接模式。 将抽象和显示解耦&#xff0c;使得两者可以独立地变化。 优缺点、应用场景 优点 抽象和实现的解耦。 这是桥梁模式的主要特点&#xff0c;它完全是为了解决继承的缺点而提出的设计模式。优…

声音生成项目(6)——在矢量量化变分编码器上使用自回归模型PixelCNN模型生成新的样本

文章目录 引言PixelCNN论文简读模型介绍自回归模型PixelCNN模型结构 基础知识回顾 代码实现PixelConvLayer具体运行过程卷积模块整体网络结构 模型执行效果问题解决训练好的模型在生成新的图片时&#xff0c;为什么要逐个元素进行生成&#xff1f;掩码卷积仅仅是考虑了一部分的…

R语言实现SMOTE与SMOGN算法解决不平衡数据的回归问题

本文介绍基于R语言中的UBL包&#xff0c;读取.csv格式的Excel表格文件&#xff0c;实现SMOTE算法与SMOGN算法&#xff0c;对机器学习、深度学习回归中&#xff0c;训练数据集不平衡的情况加以解决的具体方法。 在之前的文章Python实现SMOGN算法解决不平衡数据的回归问题&#x…

Spring初识(二)

前言 经过前面的学习,我们已经知道spring就是包含了众多方法的Ioc,那么既然是容器,就具备两个功能,我们接下来就是要介绍以下两个功能: 1.将对象存储到容器(spring)中: 2.从容器(spring)中将对象取出来. 这两个功能就应发出来,spring的创建和使用. 一.Spring创建 我们先来说…

Ubuntu关闭自动休眠

一、查看当前休眠模式 使用systemctl status sleep.target 命令查看当前休眠模式&#xff0c;结果如下图&#xff0c;sleep状态为enabled&#xff0c;表示自动休眠模式开启。 二、关闭自动休眠模式 使用sudo systemctl mask sleep.target suspend.target 关闭休眠模式 三…

面向初学者的卷积神经网络

卷积神经网络在机器学习中非常重要。如果你想做计算机视觉或图像识别任务&#xff0c;你根本离不开它们。但是很难理解它们是如何工作的。 在这篇文章中&#xff0c;我们将讨论卷积神经网络背后的机制、它的优点和应用领域。 什么是神经网络&#xff1f; 首先&#xff0c;让…