• Go常用设计模式(上)


    1 Go常用设计模式概览

    • 创建型模式
    设计模式使用场景
    单例模式全局共享一个实例,且只需要被初始化一次的场景
    工厂模式简单工厂模式:传入参数并返回一个结构体的实例;
    抽象工厂模式:返回一个接口,通过返回接口,在不公开内部实现的情况下,让调用者使用你提供的各种功能。
    工厂方法模式:将对象创建从由一个对象负责所有具体类的实例化,变成由一群子类来负责对具体类的实例化,从而将过程解耦
    • 行为型模式
    设计模式使用场景
    策略模式需要采用不同策略的场景
    模板模式需要在不改变算法框架的情况下,改变算法执行效果的场景
    • 结构型模式
    设计模式使用场景
    代理模式需要一个替身或者占位符,以控制对这个对象的访问的场景
    选项模式结构体参数很多,期望创建一个携带默认值的结构体变量,并选择性修改其中一些参数的值;
    结构体参数经常变动,变动时又不想修改创建实例的函数

    2 创建型模式

    2.1 单例模式

    老生常谈的设计模式了,单例模式就是确保全局共享一个实例,且只需要被初始化一次的场景,而Go语言的sync.Once正好可以保证全局只被执行一次。

    type Student struct {
       Id   int64
       Name string
    }
    
    var (
       once           sync.Once
       defaultStudent *Student
    )
    
    func NewStudent() *Student {
       once.Do(func() {
          defaultStudent = &Student{}
       })
       return defaultStudent
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    2.2 工厂模式
    2.2.1 简单工厂

    顾名思义,简单工厂就是非常的简单,根据输入的参数构造出想要的实例。

    type StudentConfig struct {
       DB   string
       Url  string
       Port int
    }
    
    func GetStudentDao(db, url string, port int) *StudentConfig {
       return &StudentConfig{
          Url:  url,
          DB:   db,
          Port: port,
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    2.2.2 工厂方法

    工厂方法模式在简单工厂的基础上增加了if…else…或switch来涵盖更多的选项,核心就是将不同的操作进行封装,利用具体的产出进行操作。

    type StudentDaoType int
    
    type StudentDao interface {
       Create(ctx context.Context, stu Student) bool
    }
    
    const (
       StudentDaoA StudentDaoType = 1
       StudentDaoB StudentDaoType = 2
       StudentDaoC StudentDaoType = 3
    )
    
    type StudentDaoAImpl struct{}
    
    func NewStudentDaoAImpl() *StudentDaoAImpl {
       return &StudentDaoAImpl{}
    }
    
    type StudentDaoBImpl struct{}
    
    func NewStudentDaoBImpl() *StudentDaoBImpl {
       return &StudentDaoBImpl{}
    }
    
    type StudentDaoCImpl struct{}
    
    func NewStudentDaoCImpl() *StudentDaoCImpl {
       return &StudentDaoCImpl{}
    }
    
    func (i StudentDaoAImpl) Create(ctx context.Context, stu Student) bool {
       fmt.Println("A")
       return true
    }
    
    func (i StudentDaoBImpl) Create(ctx context.Context, stu Student) bool {
       fmt.Println("B")
       return true
    }
    
    func (i StudentDaoCImpl) Create(ctx context.Context, stu Student) bool {
       fmt.Println("C")
       return true
    }
    
    func NewStudentDao(t StudentDaoType) StudentDao {
       switch t {
       case StudentDaoA:
          return NewStudentDaoAImpl()
       case StudentDaoB:
          return NewStudentDaoBImpl()
       case StudentDaoC:
          return NewStudentDaoCImpl()
       default:
          return NewStudentDaoAImpl()
       }
    }
    
    func TestFactoryMethod() {
       studentDao := NewStudentDao(StudentDaoC)
       studentDao.Create(context.TODO(), Student{})
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    2.2.3 抽象工厂

    抽象工厂相比以上两种就更加的抽象,依靠高度的抽象可以创建多个具体的实例。

    type Pen interface {
       GetPen() string
    }
    
    type Book interface {
       GetBook() string
    }
    
    type ToolFactory interface {
       CreatePen() Pen
       CreateBook() Book
    }
    
    type ShopFactory struct{}
    
    func (f *ShopFactory) CreatePen() Pen {
       return &BluePen{}
    }
    func (f *ShopFactory) CreateBook() Book {
       return &ComputerBook{}
    }
    
    type BluePen struct{}
    type ComputerBook struct{}
    
    func (p *BluePen) GetPen() string {
       return "BluePen"
    }
    func (b *ComputerBook) GetBook() string {
       return "ComputerBook"
    }
    
    func TestAbstractFactory() {
       var factory ToolFactory
       factory = &ShopFactory{}
       p1 := factory.CreatePen().GetPen()
       p2 := factory.CreateBook().GetBook()
       fmt.Printf("P1:%v\n P2:%v\n", p1, p2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    2.2.4 三者比较
    • 工厂方法模式只有一个抽象类,而抽象工厂模式有多个。

    • 工厂方法模式的具体工厂类只能创建一个具体的实例,而抽象工厂模式可以创建多个。

    • 工厂模式中的每一个形态都是针对一定问题的解决方案,工厂方法针对的是多个产品系列结构;而抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。

    3 小总结

    因为Go语言并不是严格意义上的面向对象的编程语言,而且二十三种设计模式中有一部分是需要使用到面向对象封装、继承、多肽的特性的,因此Go语言并不是完全能够且适合二十三种设计模式,但是经常用到的设计模式也是非常重要的。

  • 相关阅读:
    (原创)【B4A】一步一步入门07:EditText,文本框、密码框、键盘样式、提示文本(控件篇03)
    云原生周报 | CNCF 可观测性白皮书中文版;百度智能云服务网格产品 CSM 发布
    B树和B+树 为什么B+树更适合mysql
    BACnet/IP网关如何采集楼宇集中控制系统数据
    时间复杂度和空间复杂度详解
    【Vue简介+搭建Vue开发环境+Hello小案例】
    No module named ‘_sqlite3‘解决,亲测有效
    系统架构师--面向对象选择题
    数据结构——空间复杂度
    XPS测试中CHN含量为什么测不准?-科学指南针
  • 原文地址:https://blog.csdn.net/Mr_YanMingXin/article/details/126566304