golang创建式设计模式---工厂模式

创建式设计模式—工厂模式

目录导航

    • 创建式设计模式---工厂模式
      • 1)什么是工厂模式
      • 2)使用场景
      • 3)实现方式
      • 4)实践案例
      • 5)优缺点分析

1)什么是工厂模式

工厂模式(Factory Method Pattern)是一种设计模式,旨在创建对象时,将对象的创建与使用进行分离。通过定义一个工厂类,这个类具有创建不同具体产品对象的方法。用户只需与工厂类交互,告诉工厂自己想要什么类型的产品,工厂就会负责创建并返回相应的产品对象。这样做的好处是使得系统的架构更加清晰、灵活,方便扩展和维护产品的种类,同时也降低了代码之间耦合度。简单来说,就是有个专门负责生产对象的“地方”,根据需求生产出对应的对象。

其uml类图

在这里插入图片描述

由图可知,工厂方法模式的角色组成如下

  • 工厂(Factory):声明返回的产品对象的工厂方法的接口。该方法返回的对象类型必须与产品接口类型相匹配。
  • 具体工厂(ConCreateFactory):实现工厂接口的类,会重写基础工厂方法,使其返回不同类型的产品
  • 产品(Product):声明产品方法的接口。对于所有由具体工厂类及其子类构建的对象,该接口是通用的。
  • 具体产品(ConcreateProduct):实现产品接口的类

2)使用场景

  • 在程序开发过程中,如果开发者无法预知对象的具体类型及其依赖关系,则可以使用工厂方法模式。工厂方法模式将创建产品的工厂代码与产品代码分离,从而降低代码之间的耦合度。例如,如果需要添加一种新产品,则只需创建一个新的具体工厂类,然后重写其工厂方法。
  • 如果开发者希望其他开发者可以扩展软件库或框架的内部组件,则可以使用工厂模式。
  • 如果一个类需要通过子类指定其创建的对象,则可以使用工厂模式

3)实现方式

package modesimport "fmt"// 定义工厂接口
type Factory interface {//定义一个工厂方法,返回ProductFacMethod(user string) Product
}
// 定义一个具体的工厂类
type ConcreateFactory struct {
}
// 再实现接口的方法
func (cf *ConcreateFactory) FacMethod(user string) Product {p := &ConcreateFactory{} //创建一个具体的工厂实例return p
}
// 定义一个产品接口
type Product interface {Use()
}
//具体的产品类
type ConcreateProduct struct {
}
func (cf *ConcreateFactory) Use() {//TODO implement mefmt.Println("生产一个产品")
}

调用main.go进行测试

package mainimport "factoryMode/modes"func main() {factory := modes.ConcreateFactory{}//生产相关的产品product := factory.FacMethod("fac1")product.Use()
}

4)实践案例

使用工厂模式演示生产两种不同品牌的鞋子(以生产出Nikeaidas为例子吧)

1.定义一个产品接口TShoes,该接口有两个私有方法–setName()setSize(),以及两个公共方法----GetName()GetSize()

再定义一个shoes产品类,以及方法用于实现接口的方法,MakeShoes()则是根据shoes品牌的不同生成不同的产品对象并返回:

shoes.go

package exampleimport "fmt"// 定义鞋子产品接口
type TShoes interface {SetName(name string)SetSize(size int)GetName() stringGetSize() int
}// 定义一个shoes类
type shoes struct {name stringsize int
}func (c *shoes) SetName(name string) {c.name = name
}
func (c *shoes) GetName() string {return c.name
}func (c *shoes) SetSize(size int) {c.size = size
}
func (c *shoes) GetSize() int {return c.size
}func MakeShoes(shoesType string) (TShoes, error) {if shoesType == "Nike" {return newNike(), nil}if shoesType == "Adidas" {return newAdidas(), nil}return nil, fmt.Errorf("鞋子类型不对")
}

2.顶一个Nike产品类

package example// 生产Nike鞋子的产品类
type Nike struct {shoes
}func newNike() TShoes {return &Nike{shoes: shoes{name: "Nike shoes",size: 37,},}
}

定义Adidas产品类

package example// 生产Adidas鞋子产品
type Adidas struct {shoes
}func newAdidas() TShoes {return &Adidas{shoes: shoes{name: "Adidas shoes",size: 38,},}
}

3.main.go进行测试

package mainimport ("factoryMode/example""fmt"
)func main() {//创建一个Nike产品对象Nike, _ := example.MakeShoes("Nike")//创建一个Adidas产品对象Adidas, _ := example.MakeShoes("Adidas")PrintInformations(Nike)fmt.Println("----------")PrintInformations(Adidas)} // 此方法用于输出相关鞋子产品的信息,比如名字和尺码
func PrintInformations(s example.TShoes) {fmt.Printf("Shoes:%s", s.GetName())fmt.Println()fmt.Printf("Size:%d", s.GetSize())
}//输出结果为,Shoes:Nike shoes
Size:37---------- 
Shoes:Adidas shoes
Size:38     

5)优缺点分析

优点:

  • 应用程序具有可扩展性。在工厂模式中,调用一个方法与新类的实现是完全分离的。这种情况对如何扩展软件有特殊的影响:工厂模式具有高度的自治性,开发者在添加新类后,无须以任何方式更改程序。
  • 工厂组件具有单独可测试性。eg:如果工厂模式实现了4个或多个类,则可以单独测试每个类的功能实现

缺点:

  • 系统里的类的数量会大幅度成对增加,从而提高该系统的复杂性。工厂模式的实现会导致集成类的数量大量增加,因为每个具体的产品类都需要一个具体的工厂类。尽管工厂模式有利于软件的扩展,但是会增加工作量。如果要扩展工厂模式的产品系列,则必须要调整工厂接口和相应的具体工厂类。因此,针对所需产品类型提前进行可靠规划是非常重要的。

  • 工厂组件具有单独可测试性。eg:如果工厂模式实现了4个或多个类,则可以单独测试每个类的功能实现

缺点:

  • 系统里的类的数量会大幅度成对增加,从而提高该系统的复杂性。工厂模式的实现会导致集成类的数量大量增加,因为每个具体的产品类都需要一个具体的工厂类。尽管工厂模式有利于软件的扩展,但是会增加工作量。如果要扩展工厂模式的产品系列,则必须要调整工厂接口和相应的具体工厂类。因此,针对所需产品类型提前进行可靠规划是非常重要的。
  • 随着抽象层的引入,提高了开发者对系统的理解难度。如果下一个人要接着上一个人的进度,需要阅读和理解抽象层的代码。

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

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

相关文章

每日一题23:统计文本中单词出现的次数

一、每日一题 解答: import pandas as pd def count_occurrences(files: pd.DataFrame) -> pd.DataFrame:bull_cnt len(files[files[content].str.contains(r\sbull\s)])bear_cnt len(files[files[content].str.contains(r\sbear\s)])res_df pd.DataFrame({…

MySql基础(一)--最详细基础入门,看完就懂啦(辛苦整理,想要宝宝的赞和关注嘻嘻)

前言 希望你向太阳一样,有起有落,不失光彩~ 一、数据库概述 1. 什么是数据库 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改&…

Python 小游戏——贪吃蛇

Python 小游戏——贪吃蛇 文章目录 Python 小游戏——贪吃蛇项目介绍环境配置代码设计思路1. 初始化和变量定义2. 创建游戏窗口和FPS控制器3. 初始化贪吃蛇和食物的位置4. 控制贪吃蛇的方向和分数5. 主游戏循环 难点分析源代码呈现代码结果 项目介绍 贪吃蛇游戏是一款通过上下…

Java核心:注解处理器

Java提供了一个javac -processor命令支持处理标注有特定注解的类,来生成新的源文件,并对新生成的源文件重复执行。执行的命令大概是这样的: javac -XprintRounds -processor com.keyniu.anno.processor.ToStringProcessor com.keyniu.anno.processor.Po…

【C++】二分查找算法:x的平方根

1.题目 2.算法思路 看到题目可能不容易想到二分查找。 这题考察我们对算法的熟练程度。 二分查找的特点:数组具有二段性(不一定有序)。 题目中没有数组,我们可以造一个从0到x的数组,然后利用二分查找找到对应的值即可。 3.代码 class S…

八种单例模式

文章目录 1.单例模式基本介绍1.介绍2.单例模式八种方式 2.饿汉式(静态常量,推荐)1.基本步骤1.构造器私有化(防止new)2.类的内部创建对象3.向外暴露一个静态的公共方法 2.代码实现3.优缺点分析 3.饿汉式(静态…

如何查看热门GPT应用?

1、登陆chatgpt 2、访问 https://chatgpt.com/gpts 3、在该界面,可以搜索并使用image generator, Write For Me,Language Teature等热门应用。

【Qt 学习笔记】Qt窗口 | 菜单栏 | QMenuBar的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt窗口 | 菜单栏 | QMenuBar的使用及说明 文章编号:Qt 学习…

Go微服务: Nacos的搭建和基础API的使用

Nacos 概述 文档:https://nacos.io/docs/latest/what-is-nacos/搭建:https://nacos.io/docs/latest/quickstart/quick-start-docker/有很多种搭建方式,我们这里使用 docker 来搭建 Nacos 的搭建 这里,我们选择单机模式&#xf…

Redis可视化工具:Another Redis Desktop Manager下载安装使用

1.Github下载 github下载地址: Releases qishibo/AnotherRedisDesktopManager GitHub 2. 安装 直接双击exe文件进行安装 3. 连接Redis服务 先启动Redis服务,具体启动过程可参考: Windows安装并启动Redis服务端(zip包&#xff09…

从程序被SQL注入来MyBatis 再谈 #{} 与 ${} 的区别

缘由 最近在的一个项目上面,发现有人在给我搞 SQL 注入,我真的想说我那么点资源测试用的阿里云服务器,个人估计哈,估计能抗住他的请求。狗头.png 系统上面的截图 数据库截图 说句实在的,看到这个之后我立马就是在…

Nginx文件解析漏洞复现:CVE-2013-4547

漏洞原理 CVE-2013-4547漏洞是由于非法字符空格和截止符导致Nginx在解析URL时的有限状态机混乱,导致攻击者可以通过一个非编码空格绕过后缀名限制。假设服务器中存在文件1. jpg,则可以通过改包访问让服务器认为访问的为PHP文件。 漏洞复现 开启靶场 …

【数据结构】快速排序详解!

文章目录 1. 快速排序的非递归版本2. 快速排序2.1 hoare 版本一2.2 挖坑法 🐧版本二2.3 前后指针 版本三2.4 调用以上的三个版本的快排 3. 快速排序的优化 1. 快速排序的非递归版本 🆒🐧关键思路: 🍎① 参数中的begin…

呆马科技----构建智能可信的踏勘云平台

近年来,随着信息技术的快速发展,各个行业都在积极探索信息化的路径,以提升工作效率和服务质量。智慧踏勘云平台是基于区块链和大数据技术构建的全流程智慧可信踏勘解决平台。平台集远程视频、数据显示、工作调度、过程记录为一体,…

嵌入式进阶——舵机控制PWM

🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 舵机信号线代码示例初始化PWM初始化UART打印日志初始化外部中断Extimain函数 舵机最早用于船舶上实现转向功能,由于可以通过程序连…

Spring从零开始学使用系列(四)之@PostConstruct和@PreDestroy注解的使用

如果各位老爷觉得可以,请点赞收藏评论,谢谢啦!! 文章中涉及到的图片均由AI生成 公众号在最下方!!! 目录 1. 介绍 1.1 PostConstruct概述 1.2 PreDestroy概述 2. 基本用法 2.1 注册CommonAnn…

JS根据所选ID数组在源数据中取出对象

let selectIds [1, 3] // 选中id数组let allData [{ id: 1, name: 123 },{ id: 2, name: 234 },{ id: 3, name: 345 },{ id: 4, name: 456 },] // 源数据let newList [] // 最终数据selectIds.map((i) > {allData.filter((item) > {item.id i && newList.pus…

MyBatis复习笔记

3.Mybatis复习 3.1 xml配置 properties&#xff1a;加载配置文件 settings&#xff1a;设置驼峰映射 <settings><setting name"mapUnderscoreToCamelCase" value"true"/> </settings>typeAliases&#xff1a;类型别名设置 #这样在映射…

力扣刷题---LCS 02. 完成一半题目【简单】

题目描述 有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&…

MySQL--InnoDB体系结构

目录 一、物理存储结构 二、表空间 1.数据表空间介绍 2.数据表空间迁移 3.共享表空间 4.临时表空间 5.undo表空间 三、InnoDB内存结构 1.innodb_buffer_pool 2.innodb_log_buffer 四、InnoDB 8.0结构图例 五、InnoDB重要参数 1.redo log刷新磁盘策略 2.刷盘方式&…