当前位置: 首页 > news >正文

【golang长途旅行第38站】工厂模式

工厂模式

工厂模式是一种非常常用的创建型设计模式,它提供了一种创建对象的方式,而无需向客户端暴露对象的具体创建逻辑。在 Go 语言中,由于其本身没有构造函数和类的概念,工厂模式显得尤为重要和自然。

核心思想

核心思想是:​定义一个用于创建对象的接口(或函数),让子类(或具体实现)决定实例化哪一个类(或结构体)​。这样,客户端代码只依赖于对象的接口,而不是具体的实现,从而实现了依赖关系的解耦。

为什么在 Go 中使用工厂模式?

  1. ​隐藏创建细节​:当对象的创建过程非常复杂(例如需要依赖配置、环境变量、或者需要一系列初始化步骤)时,工厂模式可以将这些复杂性封装起来,为客户端提供一个简洁的创建接口。

  2. ​依赖接口而非实现​:客户端代码只需要知道对象提供的接口,而不需要关心其具体的实现类型。这使得代码更灵活,更容易替换和维护。

  3. ​控制实例化​:工厂函数可以控制返回的实例。例如,它可以返回一个单例、一个池化后的对象,或者根据条件返回不同子类的实例。

  4. ​命名的好处​:Go 的结构体没有构造函数。像 NewMyStruct()这样的工厂函数比 &MyStruct{}更富有表现力,尤其当初始化参数很多时,一个良好的函数名可以清晰地表达创建意图。

工厂模式的三种形式

在 Go 中,工厂模式主要有三种常见的实现形式:

  1. 简单工厂模式 (Simple Factory)
    这是最基础的形式,通常就是一个简单的函数,根据传入的参数返回不同的对象实例。
    package main

import “fmt”

// 1. 定义接口
type Logger interface {
Log(message string)
}

// 2. 定义具体实现:文件日志
type FileLogger struct{}

func (f *FileLogger) Log(message string) {
fmt.Printf(“Logging to file: %s\n”, message)
}

// 3. 定义具体实现:标准输出日志
type StdoutLogger struct{}

func (s *StdoutLogger) Log(message string) {
fmt.Printf(“Logging to stdout: %s\n”, message)
}

// 4. 工厂函数:核心所在
func NewLogger(logType string) Logger {
switch logType {
case “file”:
return &FileLogger{}
case “stdout”:
fallthrough // 落到 default
default:
return &StdoutLogger{}
}
}

// 客户端代码
func main() {
// 客户端只需要知道 Logger 接口和工厂函数
// 而不需要知道 FileLogger 或 StdoutLogger 的具体存在
var logger Logger

logger = NewLogger("file")
logger.Log("This goes to a file.") // Output: Logging to file: This goes to a file.logger = NewLogger("stdout")
logger.Log("This goes to stdout.") // Output: Logging to stdout: This goes to stdout.

}
2. 工厂方法模式 (Factory Method)
它为每一类产品提供一个独立的工厂函数,从而避免了在简单工厂中使用条件判断。

​示例:创建不同的数据库连接
package main

import “fmt”

// 数据库连接接口
type DatabaseConnector interface {
Connect()
}

// 具体实现:MySQL
type MySQLConnector struct{}

func (m *MySQLConnector) Connect() {
fmt.Println(“Connected to MySQL database.”)
}

// 工厂函数 for MySQL
func NewMySQLConnector() DatabaseConnector {
return &MySQLConnector{}
}

// 具体实现:PostgreSQL
type PostgreSQLConnector struct{}

func (p *PostgreSQLConnector) Connect() {
fmt.Println(“Connected to PostgreSQL database.”)
}

// 工厂函数 for PostgreSQL
func NewPostgreSQLConnector() DatabaseConnector {
return &PostgreSQLConnector{}
}

// 客户端代码
func main() {
// 根据需要调用不同的工厂函数
var dbConn DatabaseConnector

dbConn = NewMySQLConnector()
dbConn.Connect() // Output: Connected to MySQL database.dbConn = NewPostgreSQLConnector()
dbConn.Connect() // Output: Connected to PostgreSQL database.

}
3. 抽象工厂模式 (Abstract Factory)
这是最复杂的形式,用于创建一系列相关或依赖的对象家族,而不需要指定它们具体的类。

​示例:创建跨平台的 UI 组件
package main

import “fmt”

// ------ 抽象产品接口 ------
type Button interface {
Render()
}

type TextBox interface {
Display()
}

// ------ 抽象工厂接口 ------
type UIFactory interface {
CreateButton() Button
CreateTextBox() TextBox
}

// ------ 具体产品 & 具体工厂 for Windows ------
type WinButton struct{}

func (w WinButton) Render() {
fmt.Println(“Rendering a Windows-style button.”)
}

type WinTextBox struct{}

func (w WinTextBox) Display() {
fmt.Println(“Displaying a Windows-style textbox.”)
}

type WinFactory struct{}

func (w WinFactory) CreateButton() Button {
return WinButton{}
}
func (w WinFactory) CreateTextBox() TextBox {
return WinTextBox{}
}

// ------ 具体产品 & 具体工厂 for macOS ------
type MacButton struct{}

func (m MacButton) Render() {
fmt.Println(“Rendering a macOS-style button.”)
}

type MacTextBox struct{}

func (m MacTextBox) Display() {
fmt.Println(“Displaying a macOS-style textbox.”)
}

type MacFactory struct{}

func (m MacFactory) CreateButton() Button {
return MacButton{}
}
func (m MacFactory) CreateTextBox() TextBox {
return MacTextBox{}
}

// ------ 客户端代码 ------
// 获取一个工厂,这个工厂能创建一整套风格一致的UI组件
func GetUIFactory(platform string) UIFactory {
switch platform {
case “windows”:
return WinFactory{}
case “mac”:
return MacFactory{}
default:
panic(“unsupported platform”)
}
}

func main() {
// 根据运行环境决定使用哪个工厂
factory := GetUIFactory(“mac”) // 切换为 “windows” 试试

// 用同一个工厂创建一套协调的UI组件
button := factory.CreateButton()
textbox := factory.CreateTextBox()button.Render()   // Output: Rendering a macOS-style button.
textbox.Display() // Output: Displaying a macOS-style textbox.

}


文章转载自:

http://0WLhrrXJ.txzmy.cn
http://qCCFoW1h.txzmy.cn
http://0poRwCb1.txzmy.cn
http://LxBgSlee.txzmy.cn
http://2wZLuIMo.txzmy.cn
http://xgr2JcZP.txzmy.cn
http://hAjTnUuC.txzmy.cn
http://MRlKvlLa.txzmy.cn
http://AHFA0H7c.txzmy.cn
http://qq52aAc6.txzmy.cn
http://3YGGvcPF.txzmy.cn
http://Ir4pImG9.txzmy.cn
http://8t3IL4hN.txzmy.cn
http://O1VmPBZQ.txzmy.cn
http://AxHkgw3N.txzmy.cn
http://fxcTIgW7.txzmy.cn
http://6rRyOD1c.txzmy.cn
http://tIHcFkrd.txzmy.cn
http://tUVWhiEc.txzmy.cn
http://aYUUwexV.txzmy.cn
http://WMydwz4L.txzmy.cn
http://9CdgdZdP.txzmy.cn
http://bLo29qak.txzmy.cn
http://ZvEudBp6.txzmy.cn
http://AioEBgnT.txzmy.cn
http://2DUY53ea.txzmy.cn
http://ILGZCCR3.txzmy.cn
http://RH4Y0mIG.txzmy.cn
http://urK7R2x0.txzmy.cn
http://4yImrueg.txzmy.cn
http://www.dtcms.com/a/371131.html

相关文章:

  • 分享vscode翻译插件
  • Phthon3 学习记录-0707
  • 嵌入式学习笔记--Linux系统编程阶段--DAY07进程间通信--存储映射和共享内存
  • DMA寄存器学习
  • 对于单链表相关经典算法题:206. 反转链表及876. 链表的中间结点的解析
  • 云原生部署_k8s入门
  • 分布式数据库的历史演变与核心原理
  • 线代:排列与逆序
  • GPIO的配置中开漏输出与推挽输出的差别
  • 有有有深度学习
  • 车载通信架构 --- DoIP企业规范中细节有哪些?
  • 【Linux基础】Linux系统管理:GPT分区实践详细操作指南
  • 6-2-4 解决第一次发送失败
  • 跨域彻底讲透
  • c++之基础B(x转10进制,含十六进制)(第四课)
  • 自注意力机制解析
  • 数据结构——队列(Java)
  • Dify 从入门到精通(第 79/100 篇):Dify 的多模态模型评估(高级篇)
  • 具身导航“所想即所见”!VISTA:基于生成式视觉想象的视觉语言导航
  • synchronized 锁升级
  • 深入解析 Java 的类加载机制
  • GEE:时间序列合成一个不填补空洞,保留时间序列空像素的新影像
  • Zoom AI 技术架构研究:联合式方法与多模态集成
  • Arch Linux运维自动更新脚本推荐
  • 深度拆解OpenHarmony NFC服务:从开关到卡模拟掌握近场通信技术
  • 第5章递归:分治法
  • 【Python字符串格式化】:全面指南与最佳实践
  • MySQL学习记录-索引
  • C++进阶——继承(2)
  • Oracle体系结构-Redo Log Buffer详解