【设计模式】单例模式|最常用的设计模式

写在前面

单例模式是最常用的设计模式之一,虽然简单,但是还是有一些小坑点需要注意。本文介绍单例模式并使用go语言实现一遍单例模式。

单例模式介绍

简介

单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。

使用场景:

  1. 当类只能有一个实例而且可以从一个公开的众所周知的访问点访问它。
  2. 当这个唯一实例是通过子类化可扩展的,并且应该无须更改单例代码就能使用一个扩展的实例。

结构图
在这里插入图片描述

分类

单例里面分成了两种模式,一种是饿汉式,一种是懒汉式。

饿汉式

饿汉模式下的单例,只在使用实例的时候就创建了对象。
代码实例:

var req *Request

type Request struct {
}

func NewRequest() *Request {
	if req == nil {
		req = new(Request)
	}
	return req
}

这个代码看起来没什么问题,但是这段代码是线程不安全的。 因为如果有多个请求过来,就会同时创建多个对象,就会出现频繁的创建和删除对象,给gc造成很大的压力。

当然我们也可以加锁,但是频繁的加锁,解锁会严重影响系统的性能。

var req *Request
var lock sync.Mutex

type Request struct {
}

func NewRequest() *Request {
	lock.Lock()
	defer lock.Unlock()
	if req == nil {
		req = new(Request)
	}
	return req
}

每一个对象的创建,都需要加锁解锁,非常影响性能

懒汉式

懒汉式的单例模式可以解决我们饿汉式的缺点,并且是线程安全的,保证了我们对象全局唯一并且不会重复创建。

代码如下:

var req *Request
var reqOnce sync.Once

type Request struct {
}

func NewRequest() *Request {
	reqOnce.Do(func() {
		req = &Request{}
	})

	return req
}

这里我们用到go语言的 sync.Once 包,而sync.Once的作用就是使得我们的函数只执行一次。并且是并发安全的。

那为什么是并发安全的呢?接下来我们详解一下 sync.Once

sync.Once

sync.once 内部原理很简单,Once的结构题如下:

type Once struct {
    // done变量用来标识函数是否执行完毕
    done uint32
    // m用来保证函数执行期间,其他goroutine阻塞
    m    Mutex
}

这个Do方法是判断有无执行过这个该方法,并且是使用atomic.LoadUint32的原子操作。

func (o *Once) Do(f func()) {
    // 1.判断函数是否执行过,done=0说明没执行过
    if atomic.LoadUint32(&o.done) == 0 {
        o.doSlow(f)
    }
}
  1. 如果没执行过就执行这个方法,那么这里会有一个double check的工作,其实就是防止可能在上一次检查到这一次加锁加完的时间段间隙上有人执行完了这个函数

  2. 确认确实没有执行的时候,就执行函数,并进行原子操作标识,将 done 置为1。

func (o *Once) doSlow(f func()) {
    // 1.加锁
    o.m.Lock()
    // 5.函数返回后,释放锁
    defer o.m.Unlock()
    // 2.判断是否执行过
    if o.done == 0 {
        // 4.函数返回后,设置执行标识
        defer atomic.StoreUint32(&o.done, 1)
        // 3.具体执行函数
        f()
    }
}

应用场景举例子

我们可以在 service 上定义某一个方法的结构体函数,并将可以根据这个结构体函数进行方法的扩展。
在这里插入图片描述
在controll层只需要调用这个函数方法即可GetUserSrv()

相关推荐

  1. 常用设计模式模式和工厂模式

    2024-04-22 09:42:03       40 阅读
  2. 常考设计模式之一---模式

    2024-04-22 09:42:03       34 阅读
  3. 设计模式】:模式

    2024-04-22 09:42:03       55 阅读
  4. 设计模式——模式

    2024-04-22 09:42:03       64 阅读
  5. 设计模式模式

    2024-04-22 09:42:03       67 阅读
  6. 设计模式——模式

    2024-04-22 09:42:03       62 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-22 09:42:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-22 09:42:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-22 09:42:03       82 阅读
  4. Python语言-面向对象

    2024-04-22 09:42:03       91 阅读

热门阅读

  1. C 练习实例13

    2024-04-22 09:42:03       31 阅读
  2. TensorFlow的基本概念及使用场景

    2024-04-22 09:42:03       37 阅读
  3. Oracle

    2024-04-22 09:42:03       40 阅读
  4. 【大模型系列】提示学习

    2024-04-22 09:42:03       37 阅读
  5. 冰狐智能辅助和按键精灵如何选择?

    2024-04-22 09:42:03       39 阅读