11 | 设计模式:Go常用设计模式概述
孔令飞
该思维导图由 AI 生成,仅供参考
你好,我是孔令飞,今天我们来聊聊 Go 项目开发中常用的设计模式。
在软件开发中,经常会遇到各种各样的编码场景,这些场景往往重复发生,因此具有典型性。针对这些典型场景,我们可以自己编码解决,也可以采取更为省时省力的方式:直接采用设计模式。
设计模式是啥呢?简单来说,就是将软件开发中需要重复性解决的编码场景,按最佳实践的方式抽象成一个模型,模型描述的解决方法就是设计模式。使用设计模式,可以使代码更易于理解,保证代码的重用性和可靠性。
在软件领域,GoF(四人帮,全拼 Gang of Four)首次系统化提出了 3 大类、共 25 种可复用的经典设计方案,来解决常见的软件设计问题,为可复用软件设计奠定了一定的理论基础。
从总体上说,这些设计模式可以分为创建型模式、结构型模式、行为型模式 3 大类,用来完成不同的场景。这一讲,我会介绍几个在 Go 项目开发中比较常用的设计模式,帮助你用更加简单快捷的方法应对不同的编码场景。其中,简单工厂模式、抽象工厂模式和工厂方法模式都属于工厂模式,我会把它们放在一起讲解。
创建型模式
首先来看创建型模式(Creational Patterns),它提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了Go项目开发中常用的设计模式,包括单例模式、工厂模式、策略模式、模板模式和代理模式。同时,还介绍了选项模式在Go项目开发中的应用。单例模式适用于需要全局共享且只需初始化一次的场景,工厂模式提供了创建对象的方式,策略模式定义一组算法并使其可以互换,模板模式定义了操作中算法的骨架,代理模式可以为另一个对象提供一个替身或者占位符。而选项模式则可以创建一个带有默认值的struct变量,并选择性地修改其中一些参数的值,在Go项目开发中有着广泛的应用。文章通过具体的代码示例和对比分析,清晰地展示了选项模式的实现方式及其优势。通过这些设计模式,读者可以更简洁明了地处理不同的编码场景,提高代码的可重用性和可靠性。文章还提到了选项模式的适用场景和注意事项,为读者提供了实际应用的指导。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 语言项目开发实战》,新⼈⾸单¥68
《Go 语言项目开发实战》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(52)
- 最新
- 精选
- Geek_947b62func GetIns() *singleton { if ins == nil { mu.Lock() defer mu.Unlock() ins = &singleton{} } return ins} 这里有可能两个线程同时进入到if判断的,会出现多次实例化的。所以应该在加锁之后再判断一次才行。 func GetIns() *singleton { if ins == nil { mu.Lock() defer mu.Unlock() if ins == nil { ins = &singleton{} } } return ins }
作者回复: 是的,文章有问题,我找编辑修改下,感谢反馈!
2021-06-19424 - ppd0705请问`GetCacheInsOr`里面的 “Or”是什么的缩写?
作者回复: OrDie,OrPanic,OrXxx类似这种缩写,省略掉Die、Panic、Xxx说明这个函数可能会Die、Panic、Xxx,总之意思是当条件不满足时,会发生一些不一样的事情。
2021-07-0718 - serverlessfunc GetIns() *singleton { if ins == nil { mu.Lock() defer mu.Unlock() if ins == nil { ins = &singleton{} } } return ins } 滥用 defer 嫌疑,建议改成 func GetIns() *singleton { if ins == nil { mu.Lock() if ins == nil { ins = &singleton{} } mu.Unlock() } return ins }
作者回复: 老哥名字起得很屌,建议也很专业!我让老师改下。一种是函数级别的锁,一种是变量级别的锁。这里确实没必要用到函数级别的锁,只锁变量及其初始化就可以了。
2021-06-26312 - Ryoma咱就是说,行为型和结构型有没有可能弄反了= =
作者回复: 之前确实反了,后来有更正过,难道打盹了没更正?我check下
2022-06-14归属地:广东25 - Hector请问老师,在选项模式中,使用了Option接口的意义是为了什么,这样做增加了代码的复杂度,为什么不在WithTimeout函数中直接返回optionFunc?
作者回复: 通过接口强制要求optionFunc都要有apply方法
2021-08-1175 - yandongxiao总结: 1. 设计模式共计25种,分为三类:创建型模式、结构性模式、行为模式 2. 创建型模式包括:单例模式(懒汉模式、饿汉模式、并发安全)、工厂模式(简单工厂、抽象工厂、工厂方法) 3. 结构性模式:策略模式和模板模式。隐含了对扩展开放、对修改关闭的原则。 4. 行为模式:代理模式、选项模式。
作者回复: 6666
2021-11-244 - Dpp的小跟班儿简单工厂模式的示例代码那里,最后返回应该是 return &Person{XXX,XXX,},NewPerson方法的返回值类型是指针
作者回复: 感谢反馈,我们更新下
2021-06-234 - Vackine单例模式的实现里面是不是还要加一个只读的逻辑啊,万一获取了之后,对其修改了不就不一样了?
作者回复: 是的哈,更新了,感谢反馈
2021-06-204 - jack实际工作中,个人觉得选项模式的接口可以取消掉,虽然扩展性会好一些,封装起来倒是更复杂了 type Connection struct { addr string age int } // 定义返回当前对象修改的指针方法 type Option func(*Connection) func withAge(age int) Option { return func(c *Connection) { c.age = age } } func newConnection(addr string, opts ...Option) *Connection { connection := &Connection{ addr: addr, age: 666, } for _, apply := range opts { apply(connection) } return connection }
作者回复: 封装起来会有点复杂度,但是后期比较好维护和理解
2022-09-15归属地:广东2 - aoe适用选项模式的场景也适用于建造者模式(Builder),对比代码如下 选项模式创建对象 ```go func main() { conn, err := options.NewConnect("http://localhost:8080", options.WithTimeout(time.Second*10), options.WithCaching(true)) if err != nil { log.Fatal(err) } fmt.Println("conn:", conn) } ``` 建造者模式创建对象 ```go package main import ( "fmt" "time" ) type Connection struct { addr string cache bool timeout time.Duration } type ConnectionBuilder struct { connection *Connection } func Builder() *ConnectionBuilder { return &ConnectionBuilder{&Connection{}} } func (c *ConnectionBuilder) WithAddr(addr string) *ConnectionBuilder { c.connection.addr = addr return c } func (c *ConnectionBuilder) WithCaching(cache bool) *ConnectionBuilder { c.connection.cache = cache return c } func (c *ConnectionBuilder) WithTimeout(t time.Duration) *ConnectionBuilder { c.connection.timeout = t return c } func (c *ConnectionBuilder) Build() Connection { return *c.connection } func main() { connBuilder := Builder() connBuilder. WithAddr("http://localhost:8080"). WithCaching(true). WithTimeout(time.Second * 10) conn := connBuilder.Build() fmt.Println("conn:", conn) } ```
作者回复: 6666
2022-03-142
收起评论