Golang 常用的五种创建型设计模式

news/2024/10/19 13:18:13
Golang 常用的五种创建型设计模式
原创 Go Official Blog Go Official Blog
 2024年10月18日 19:10 中国香港 听全文
在 Go 中,创建设计模式有助于管理对象的创建,并控制对象的实例化方式。这些模式在对象创建过程复杂或需要特殊处理时特别有用。以下是 Go 中常用的主要创建模式:
 
单例模式
单例模式确保一个类只有一个实例,并提供一个全局访问点。
 
如何实现
定义一个结构,并将其作为单个实例。
为该结构创建一个全局变量,但不要立即将其初始化。
使用 sync.Once 确保实例只创建一次,即使在多线程情况下也是如此。
提供一个全局函数来返回实例。
以下是实现单例模式的基本示例:
 
package main
 
import (
 "fmt"
 "sync"
)
 
type (
 singleton struct {
  data string
 }
)
 
var instance *singleton
var once sync.Once
 
// Function to return the single instance
func GetInstance() *singleton {
 // Use sync.Once to ensure the instance is created only once
 once.Do(func() {
  instance = &singleton{data: "This is a singleton"}
 })
 
 return instance
}
 
func main() {
 s1 := GetInstance()
 s2 := GetInstance()
 
 // Both should point to the same instance
 fmt.Println(s1 == s2) // true
 fmt.Println(s1.data) // "This is a singleton"
}
sync.Once 可确保实例只创建一次,即使在并发调用 GetInstance 的情况下也是如此。
 
工厂方法模式
工厂方法模式定义了创建对象的接口,但允许子类改变将创建的对象类型。在 Go 中,这可以通过创建工厂函数来实现。这种设计模式提供一种将实例化逻辑委托给子类的方法,从而可以灵活地创建对象。
 
实现步骤:
 
创建一个为不同对象定义通用行为的接口。
创建多个实现此接口的结构体。
创建一个函数(工厂方法),接收一些输入(如类型)并返回相应结构的实例。
以下是实现工厂方法模式的基本示例:
 
package main
 
import (
 "fmt"
)
 
type Animal interface {
  Speak() string
 }
 
 Dog struct{}
 Cat struct{}
)
 
func (d Dog) Speak() string {
 return "Woof!"
}
 
func (c Cat) Speak() string {
 return "Meow!"
}
 
func AnimalFactory(animalType string) Animal {
 if animalType == "dog" {
  return &Dog{}
 } else if animalType == "cat" {
  return &Cat{}
 }
 return nil
}
 
func main() {
 dog := AnimalFactory("dog")
 fmt.Println(dog.Speak()) // Woof!
 
 cat := AnimalFactory("cat")
 fmt.Println(cat.Speak()) // Meow!
}
工厂方法允许创建不同类型的对象,但用户端隐藏了创建逻辑。当对象创建过程比较复杂,需要进行抽象时,这种模式尤其有用。
 
抽象工厂模式
抽象工厂(Abstract Factory)提供了一个接口,用于创建相关或依赖对象的族,而无需指定它们的具体类。在 Go 中,可以通过定义不同的工厂接口来实现它。
 
 
当系统需要独立于其对象的创建、组成和表示方式时,它就非常有用。它允许创建相关对象族。
 
以下是实现抽象工厂模式的基本示例:
 
 
package main
 
import (
 "fmt"
)
 
// Define an abstract factory
type (
 GUIFactory interface {
  CreateButton() Button
  CreateCheckbox() Checkbox
 }
)
 
// Define interfaces for products
type (
 Button interface {
  Press() string
 }
 
 Checkbox interface {
  Check() string
 }
 
 // Implement concrete products for Windows
 WindowsButton struct{}
 WindowsCheckbox struct{}
 
 // Implement concrete products for Mac
 MacButton struct{}
 MacCheckbox struct{}
 
 // Implement factories for each platform
 WindowsFactory struct{}
 MacFactory struct{}
)
 
func (w *WindowsButton) Press() string { return "Windows Button Pressed" }
 
func (w *WindowsCheckbox) Check() string { return "Windows Checkbox Checked" }
 
func (m *MacButton) Press() string { return "Mac Button Pressed" }
 
func (m *MacCheckbox) Check() string { return "Mac Checkbox Checked" }
 
func (w *WindowsFactory) CreateButton() Button { return &WindowsButton{} }
func (w *WindowsFactory) CreateCheckbox() Checkbox { return &WindowsCheckbox{} }
 
func (m *MacFactory) CreateButton() Button { return &MacButton{} }
func (m *MacFactory) CreateCheckbox() Checkbox { return &MacCheckbox{} }
 
func main() {
 // Get a Windows factory
 var wf GUIFactory = &WindowsFactory{}
 button := wf.CreateButton()
 checkbox := wf.CreateCheckbox()
 
 fmt.Println(button.Press()) // Output: Windows Button Pressed
 fmt.Println(checkbox.Check()) // Output: Windows Checkbox Checked
 
 var mf GUIFactory = &MacFactory{}
 button = mf.CreateButton()
 checkbox = mf.CreateCheckbox()
 
 fmt.Println(button.Press()) // Output: Mac Button Pressed
 fmt.Println(checkbox.Check()) // Output: Mac Checkbox Checked
}
Builder 模式
 
构建器模式将复杂对象的构建与其表示分离开来,允许同一构建过程创建不同的表示。它能解决问题:复杂的对象通常是一步一步构建的。构建器模式为创建此类对象提供了灵活的解决方案,分解了实例化过程。
 
以下是实现构建器模式的基本示例:
 
package main
 
import (
 "fmt"
)
 
// Product to be built
type House struct {
  windows string
  doors string
  roof string
 }
 
 // Concrete builder for a villa
 type VillaBuilder struct {
  house House
 }
 
 // Director controls the building process
 type Director struct {
  builder HouseBuilder
 }
)
 
// Builder interface
type HouseBuilder interface {
  SetWindows() HouseBuilder
  SetDoors() HouseBuilder
  SetRoof() HouseBuilder
  Build() *House
 }
 
 
func (v *VillaBuilder) SetWindows() HouseBuilder {
 v.house.windows = "Villa Windows"
 return v
}
 
func (v *VillaBuilder) SetDoors() HouseBuilder {
 v.house.doors = "Villa Doors"
 return v
}
 
func (v *VillaBuilder) SetRoof() HouseBuilder {
 v.house.roof = "Villa Roof"
 return v
}
 
func (v *VillaBuilder) Build() *House {
 return &v.house
}
 
func (d *Director) Construct() *House {
 return d.builder.SetWindows().SetDoors().SetRoof().Build()
}
 
func main() {
 director := &Director{}
 
 // Build a villa
 v_builder := &VillaBuilder{}
 director.builder = v_builder
 villa := director.Construct()
 fmt.Println(*villa) // Output: {Villa Windows Villa Doors Villa Roof}
}
在创建需要大量可选配置的复杂对象时,创建者模式非常有用。
 
原型模式
原型模式允许通过复制现有对象(原型)来创建新对象,而不是从头开始创建。当创建一个新对象的成本很高,而现有对象又可以克隆重用时,原型模式就派上用场了。
 
以下是实现原型模式的基本示例
 
package main
 
import (
 "fmt"
)
 
// Cloneable interface
type (
 Cloneable interface {
  Clone() Cloneable
 }
)
 
// Concrete struct (prototype)
type (
 Product struct {
  name string
  category string
 }
)
 
// Clone method creates a copy of the Product
func (p *Product) Clone() Cloneable {
 return &Product{name: p.name, category: p.category}
}
 
func (p *Product) SetName(name string) {
 p.name = name
}
 
func (p *Product) GetDetails() string {
 return fmt.Sprintf("Product Name: %s, Category: %s", p.name, p.category)
}
 
func main() {
 // Original product
 original := &Product{name: "Phone", category: "Electronics"}
 fmt.Println(original.GetDetails()) // Output: Product Name: Phone, Category: Electronics
 
 // Clone the product and change its name
 cloned := original.Clone().(*Product)
 cloned.SetName("Smartphone")
 fmt.Println(cloned.GetDetails()) // Output: Product Name: Smartphone, Category: Electronics
}
当创建对象的成本很高,而你又想通过复制现有对象来创建多个类似对象时,原型模式就很有效。这种模式通过克隆现有实例来简化对象的创建,而不是从头开始创建新实例。
 
总结
每种模式都有其特定的用例,选择恰当的设计模式会使代码更有条理、可重用且更易于维护!
 
 
 
 
Go Official Blog
 你的肯定是对我最大的鼓励 
 
 
阅读原文
阅读 630
 
 

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

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

相关文章

虚拟歌姬列传

前言:纵观歌姬历史,初为Vocaloid一匡天下,然今群雄竞起,UTAU,SV群英荟萃,大有百花齐放之态也,今当尽绵薄之力,浅修其史,以说心也 啊啊啊 初音ミク重音テト(SV)重音テト(UTAU)(v)FlowerGUMI镜音レン,镜音リン巡音ルカ可不(KAFU)歌爱雪IAVY1MEIKOKAITO花隈千冬

virtualBox环境Ubuntu升级后太卡,转debian很丝滑

之前一直在virtualBox中用Ubuntu折腾开发环境,前段时间升级到24后,感觉好卡 什么都不做资源就用完了转到更稳定的上游Debian 稳的一批

sicp每日一题[2.49]

Exercise 2.49Use segments->painter to define the following primitive painters:a. The painter that draws the outline of the designated frame. b. The painter that draws an “X” by connecting opposite corners of the frame. c. The painter that draws a diam…

数据采集与融合技术实验课程作业二

数据采集与融合技术实验课程作业二作业所属课程 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology作业链接 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology/homework/13285gitee码云代码位置 https://gitee.com/wang-qi…

spark sql语句性能优化及执行计划

一、优化点:1、not in 替换为 not exist;2、in 替换为 right join;3、distinct 替换为 group by;4、count(distinct) 替换为 count;5、where条件中,等号左右两边的数据类型需要一致;6、where条件中,等号左边不要有函数;7、where条件上移;8、优化点需要对照执行计划,并…

GDPC-CSA::CTF一轮web题目write up-T2 ez http

首先来看题目先不鸟提示,进去页面逛逛,F12一下,看到如下内容回头来看提示,robots.txt是网页用来告知爬虫允许和禁止访问文件的君子协议,由题我们决定先打开/robots.txt查看一下爬虫被禁止访问哪些文件,其中说不定会有线索 如果对robots.txt还不了解的可以看看这里 在网站…