Go语言设计模式:创建型模式
Go语言设计模式:创建型模式
一、设计模式概述
设计模式是软件设计中反复出现问题的解决方案。Go语言作为一种现代化的编程语言,同样可以应用经典的设计模式。
Go语言中的设计模式特点
- 接口优先:通过接口实现解耦
- 组合优于继承:Go不支持继承,使用组合实现代码复用
- 并发安全:考虑并发场景下的设计
- 简洁性:避免过度设计
二、单例模式
单例模式确保一个类只有一个实例,并提供全局访问点。
饿汉式单例
package singleton import "sync" type Singleton struct { data string } var instance *Singleton var once sync.Once func GetInstance() *Singleton { once.Do(func() { instance = &Singleton{ data: "initialized", } }) return instance } func (s *Singleton) SetData(data string) { s.data = data } func (s *Singleton) GetData() string { return s.data }懒汉式单例(带缓存)
package singleton import ( "sync" "time" ) type Config struct { timeout time.Duration retries int } var ( configInstance *Config configMu sync.RWMutex ) func GetConfig() *Config { // 先检查(快速路径) configMu.RLock() if configInstance != nil { defer configMu.RUnlock() return configInstance } configMu.RUnlock() // 需要初始化,获取写锁 configMu.Lock() defer configMu.Unlock() // 双重检查 if configInstance == nil { configInstance = &Config{ timeout: 30 * time.Second, retries: 3, } } return configInstance }三、工厂模式
工厂模式封装对象的创建过程,使客户端代码与具体实现解耦。
简单工厂
package factory type Product interface { GetName() string } type ConcreteProductA struct{} func (p *ConcreteProductA) GetName() string { return "Product A" } type ConcreteProductB struct{} func (p *ConcreteProductB) GetName() string { return "Product B" } func NewProduct(productType string) Product { switch productType { case "A": return &ConcreteProductA{} case "B": return &ConcreteProductB{} default: return nil } }工厂方法
package factory type Factory interface { CreateProduct() Product } type ConcreteFactoryA struct{} func (f *ConcreteFactoryA) CreateProduct() Product { return &ConcreteProductA{} } type ConcreteFactoryB struct{} func (f *ConcreteFactoryB) CreateProduct() Product { return &ConcreteProductB{} } func main() { var factory Factory = &ConcreteFactoryA{} product := factory.CreateProduct() println(product.GetName()) }抽象工厂
package factory type Button interface { Click() string } type Checkbox interface { Check() string } type GUIFactory interface { CreateButton() Button CreateCheckbox() Checkbox } type WindowsButton struct{} func (b *WindowsButton) Click() string { return "Windows button clicked" } type WindowsCheckbox struct{} func (c *WindowsCheckbox) Check() string { return "Windows checkbox checked" } type WindowsFactory struct{} func (f *WindowsFactory) CreateButton() Button { return &WindowsButton{} } func (f *WindowsFactory) CreateCheckbox() Checkbox { return &WindowsCheckbox{} }四、建造者模式
建造者模式将复杂对象的构建过程与其表示分离,使同样的构建过程可以创建不同的表示。
package builder type Product struct { PartA string PartB string PartC string } type Builder interface { BuildPartA() BuildPartB() BuildPartC() GetProduct() *Product } type ConcreteBuilder struct { product *Product } func NewConcreteBuilder() *ConcreteBuilder { return &ConcreteBuilder{ product: &Product{}, } } func (b *ConcreteBuilder) BuildPartA() { b.product.PartA = "Part A" } func (b *ConcreteBuilder) BuildPartB() { b.product.PartB = "Part B" } func (b *ConcreteBuilder) BuildPartC() { b.product.PartC = "Part C" } func (b *ConcreteBuilder) GetProduct() *Product { return b.product } type Director struct { builder Builder } func (d *Director) Construct() *Product { d.builder.BuildPartA() d.builder.BuildPartB() d.builder.BuildPartC() return d.builder.GetProduct() }五、原型模式
原型模式通过复制现有对象来创建新对象,避免重复的初始化过程。
package prototype import "encoding/json" type Prototype interface { Clone() Prototype } type ConcretePrototype struct { ID int Name string Items []string } func (p *ConcretePrototype) Clone() Prototype { // 深拷贝 data, _ := json.Marshal(p) clone := &ConcretePrototype{} json.Unmarshal(data, clone) return clone } func (p *ConcretePrototype) CloneShallow() Prototype { // 浅拷贝 clone := *p return &clone }六、抽象工厂模式实战
场景:数据库连接工厂
package factory import "database/sql" type Database interface { Connect() error Query(sql string) (*sql.Rows, error) Close() error } type DatabaseFactory interface { CreateDatabase(config map[string]string) Database } type MySQLDatabase struct { conn *sql.DB } func (m *MySQLDatabase) Connect() error { // MySQL连接逻辑 return nil } func (m *MySQLDatabase) Query(sql string) (*sql.Rows, error) { // 查询逻辑 return nil, nil } func (m *MySQLDatabase) Close() error { return m.conn.Close() } type MySQLFactory struct{} func (f *MySQLFactory) CreateDatabase(config map[string]string) Database { return &MySQLDatabase{} } func NewDatabaseFactory(dbType string) DatabaseFactory { switch dbType { case "mysql": return &MySQLFactory{} case "postgres": return &PostgresFactory{} default: return nil } }七、单例模式实战
场景:日志管理器
package logger import ( "sync" "io" "os" ) type Logger struct { writer io.Writer } var ( loggerInstance *Logger loggerOnce sync.Once ) func GetLogger() *Logger { loggerOnce.Do(func() { file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { file = os.Stdout } loggerInstance = &Logger{ writer: file, } }) return loggerInstance } func (l *Logger) Log(message string) { l.writer.Write([]byte(message + "\n")) }八、建造者模式实战
场景:HTTP客户端配置
package client import ( "net/http" "time" ) type HTTPClient struct { client *http.Client baseURL string timeout time.Duration headers map[string]string } type HTTPClientBuilder struct { baseURL string timeout time.Duration headers map[string]string } func NewHTTPClientBuilder() *HTTPClientBuilder { return &HTTPClientBuilder{ timeout: 30 * time.Second, headers: make(map[string]string), } } func (b *HTTPClientBuilder) WithBaseURL(url string) *HTTPClientBuilder { b.baseURL = url return b } func (b *HTTPClientBuilder) WithTimeout(timeout time.Duration) *HTTPClientBuilder { b.timeout = timeout return b } func (b *HTTPClientBuilder) WithHeader(key, value string) *HTTPClientBuilder { b.headers[key] = value return b } func (b *HTTPClientBuilder) Build() *HTTPClient { client := &http.Client{ Timeout: b.timeout, } return &HTTPClient{ client: client, baseURL: b.baseURL, timeout: b.timeout, headers: b.headers, } }九、总结
创建型设计模式帮助我们管理对象的创建过程:
- 单例模式:确保全局唯一实例
- 工厂模式:封装对象创建逻辑
- 抽象工厂模式:创建一系列相关对象
- 建造者模式:分步构建复杂对象
- 原型模式:通过复制创建对象
在Go语言中应用这些模式时,要注意:
- 利用接口实现解耦
- 考虑并发安全性
- 避免过度设计
- 保持代码简洁
选择合适的设计模式可以提高代码的可维护性和可扩展性。
