Go 语言项目开发实战
孔令飞
腾讯云专家工程师,前 Red Hat、联想云工程师
41030 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 61 讲
Go 语言项目开发实战
15
15
1.0x
00:00/00:00
登录|注册

11 | 设计模式:Go常用设计模式概述

实现选项模式
Option接口
定义选项结构体
火车代理点
火车站
具体子类实现
具体步骤封装
定义抽象类
策略执行者
策略实现
定义策略接口
工厂方法模式
抽象工厂模式
简单工厂模式
使用sync.Once的实现
带检查锁的实现
懒汉方式
饿汉方式
选项模式
代理模式
模板模式
策略模式
工厂模式
单例模式
行为型模式
结构型模式
创建型模式
Go常用设计模式概述

该思维导图由 AI 生成,仅供参考

你好,我是孔令飞,今天我们来聊聊 Go 项目开发中常用的设计模式。
在软件开发中,经常会遇到各种各样的编码场景,这些场景往往重复发生,因此具有典型性。针对这些典型场景,我们可以自己编码解决,也可以采取更为省时省力的方式:直接采用设计模式。
设计模式是啥呢?简单来说,就是将软件开发中需要重复性解决的编码场景,按最佳实践的方式抽象成一个模型,模型描述的解决方法就是设计模式。使用设计模式,可以使代码更易于理解,保证代码的重用性和可靠性。
在软件领域,GoF(四人帮,全拼 Gang of Four)首次系统化提出了 3 大类、共 25 种可复用的经典设计方案,来解决常见的软件设计问题,为可复用软件设计奠定了一定的理论基础。
从总体上说,这些设计模式可以分为创建型模式、结构型模式、行为型模式 3 大类,用来完成不同的场景。这一讲,我会介绍几个在 Go 项目开发中比较常用的设计模式,帮助你用更加简单快捷的方法应对不同的编码场景。其中,简单工厂模式、抽象工厂模式和工厂方法模式都属于工厂模式,我会把它们放在一起讲解。

创建型模式

首先来看创建型模式(Creational Patterns),它提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了Go项目开发中常用的设计模式,包括单例模式、工厂模式、策略模式、模板模式和代理模式。同时,还介绍了选项模式在Go项目开发中的应用。单例模式适用于需要全局共享且只需初始化一次的场景,工厂模式提供了创建对象的方式,策略模式定义一组算法并使其可以互换,模板模式定义了操作中算法的骨架,代理模式可以为另一个对象提供一个替身或者占位符。而选项模式则可以创建一个带有默认值的struct变量,并选择性地修改其中一些参数的值,在Go项目开发中有着广泛的应用。文章通过具体的代码示例和对比分析,清晰地展示了选项模式的实现方式及其优势。通过这些设计模式,读者可以更简洁明了地处理不同的编码场景,提高代码的可重用性和可靠性。文章还提到了选项模式的适用场景和注意事项,为读者提供了实际应用的指导。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 语言项目开发实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(52)

  • 最新
  • 精选
  • Geek_947b62
    func 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-19
    4
    24
  • ppd0705
    请问`GetCacheInsOr`里面的 “Or”是什么的缩写?

    作者回复: OrDie,OrPanic,OrXxx类似这种缩写,省略掉Die、Panic、Xxx说明这个函数可能会Die、Panic、Xxx,总之意思是当条件不满足时,会发生一些不一样的事情。

    2021-07-07
    18
  • serverless
    func 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-26
    3
    12
  • Ryoma
    咱就是说,行为型和结构型有没有可能弄反了= =

    作者回复: 之前确实反了,后来有更正过,难道打盹了没更正?我check下

    2022-06-14归属地:广东
    2
    5
  • Hector
    请问老师,在选项模式中,使用了Option接口的意义是为了什么,这样做增加了代码的复杂度,为什么不在WithTimeout函数中直接返回optionFunc?

    作者回复: 通过接口强制要求optionFunc都要有apply方法

    2021-08-11
    7
    5
  • yandongxiao
    总结: 1. 设计模式共计25种,分为三类:创建型模式、结构性模式、行为模式 2. 创建型模式包括:单例模式(懒汉模式、饿汉模式、并发安全)、工厂模式(简单工厂、抽象工厂、工厂方法) 3. 结构性模式:策略模式和模板模式。隐含了对扩展开放、对修改关闭的原则。 4. 行为模式:代理模式、选项模式。

    作者回复: 6666

    2021-11-24
    4
  • Dpp的小跟班儿
    简单工厂模式的示例代码那里,最后返回应该是 return &Person{XXX,XXX,},NewPerson方法的返回值类型是指针

    作者回复: 感谢反馈,我们更新下

    2021-06-23
    4
  • Vackine
    单例模式的实现里面是不是还要加一个只读的逻辑啊,万一获取了之后,对其修改了不就不一样了?

    作者回复: 是的哈,更新了,感谢反馈

    2021-06-20
    4
  • 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-14
    2
收起评论
显示
设置
留言
52
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部