Go设计模式(6)-单例模式

简介: 前面5篇文章讲解了设计模式的语法、面向对象分析、原则、代码编写、类图表示法,从本文开始讲述23种设计模式。

1.说明

前面5篇文章讲解了设计模式的语法、面向对象分析、原则、代码编写、类图表示法,从本文开始讲述23种设计模式。

后面会按照创建型、结构型、行为型的顺序来写

  1. 创建型5个:单例模式、简单工厂、工厂模式、建造者模式、原型模式 ,主要解决“对象的创建”问题
  2. 结构型7:代理模式、桥接模式、装饰器模式、适配器模式、门面模式 、组合模式、享元模式,主要解决“类或对象的组合或组装”问题
  3. 行为型11:观察者模式、模板模式、策略模式、职责链模式、状态模式、迭代器模式、访问者模式、备忘录模式、命令模式、解释器模式、中介模式,主要解决“类或对象之间的交互”问题

有7个模式并不太常用,他们分别是:组合模式、享元模式、状态模式、访问者模式、命令模式、解释器模式、中介模式,所以常用的设计模式16个。

每篇文章尽量都会有类图、定义、分析、使用场景、实现、代码、扩展等信息。之所以包含这些信息,因为对于很多人来说,你问他个具体的设计原则、思想、模式的原理和实现,他都能回答得头头是道,但是,在实际的项目开发中,写出来的代码质量还是很差。这种情况出现的原因还是,相关的知识点都过于抽象,通俗点讲就是有点“假大空”,不够具体、不太能落地,所以导致理论和实践容易脱节。

2.定义

2.1单例模式

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

UML类图:链接为https://www.processon.com/view/link/6080def6079129456d4beecf

image-20210420131156614.png

2.2分析

通过分析能够看出以下几点:

  1. 单例模式能够保证类只有一个实例,就是类图里的instance
  2. 有方法能够让外部访问到该实例,就是类图里的GetInstance
  3. 外部无法创建实例,是因为构造函数为私有函数,外部无法访问,自然也就无法生成实例

3.使用场景

单例模式理解相对简单,一般在哪些场景下我们会用到单例模式呢?

  1. 多线程情况下会导致资源访问冲突

    • 如项目需要写Log,而且Log一般会写入同一个文件。如果存在多个Log对象,即使Log有对象级别的锁,但在多线程下完全无用,日志仍然会乱序。解决这个问题我们可以使用类级别锁、分布式锁,但是都相对麻烦一些。如果使用单例模式,则Log只需保持对象级别锁就可以解决资源访问冲突
  2. 需要保证全局唯一的类

    • 比如配置类,这种只应该存在一份

4.代码

单例模式的实现的时候需要考虑如下问题:

  1. 对象创建时线程安全问题
  2. 是否支持延迟加载
  3. getInstance()性能是否高

根据语言不同,实现方式也不一样,一般有饿汉式、懒汉式、双重检测、静态内部类、枚举等。无论使用哪种方式,核心目的都是为了只会生成一个实例

这里多少解释一下饿汉式和懒汉式。饿汉式可以简单的理解为实例提前创建好了,getInstance只是获取实例返回。懒汉式是调用getInstance的时候,getInstance负责生成唯一实例。两者各有优缺点,饿汉式不必考虑线程安全问题,实例生成的成本放在项目启动时,但不支持延迟加载;懒汉式需要考虑线程安全问题,支持延迟加载。

具体实现以前在文章Go单例实现方案中写过,实现方式比较简单

/**
@date: 2021/4/22
单例模式
**/
package design

import (
    "fmt"
    "sync"
)

type singleTon struct {
}

func (s *singleTon) Show() {
    fmt.Println("hello world")
}

var (
    once   sync.Once
    single *singleTon
)

func GetSingleInstance() *singleTon {
    once.Do(func() {
        single = &singleTon{}
    })
    return single
}
func main() {
    single := design.GetSingleInstance()
    single.Show()
}

关于代码,此处说明几点:

  1. 使用sync.Once.Do,轻松解决线程安全问题,确保只会有一个实例
  2. singleTon类首字母需要小写,这样能够保证非design的包无法创建单例类。如下图所示,main包无法获取到singleTon类

image-20210422094017975.png

  1. 此处的实现方式是懒汉式,如果想使用饿汉式,可以使用init或者项目启动初始化时直接调用,具体实现大家可自己完成
  2. 具体代码可以查看:https://github.com/shidawuhen/asap/blob/master/controller/design/6single.go

5.总结

单例模式作为简单、常用的模式是一定需要掌握的。但单例模式也有一些缺点,如在继承、多态方面能力会弱一些,是否使用单例模式需要依据具体情况而定。另外单例模式也可以扩展到集群环境下、可以扩展为多例模式,这些内容大家有兴趣可以研究一下。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

往期文章回顾:

招聘

  1. 字节跳动|抖音电商服务端技术岗位虚位以待
  2. 字节跳动招聘专题

设计模式

  1. Go设计模式(5)-类图符号表示法
  2. Go设计模式(4)-代码编写优化
  3. Go设计模式(4)-代码编写
  4. Go设计模式(3)-设计原则
  5. Go设计模式(2)-面向对象分析与设计
  6. Go设计模式(1)-语法

语言

  1. Go工具之generate
  2. Go单例实现方案
  3. Go通道实现原理
  4. Go定时器实现原理
  5. Beego框架使用
  6. Golang源码BUG追查
  7. Gin框架简洁版
  8. Gin源码剖析

架构

  1. 支付接入常规问题
  2. 限流实现2
  3. 秒杀系统
  4. 分布式系统与一致性协议
  5. 微服务之服务框架和注册中心
  6. 浅谈微服务
  7. 限流实现1
  8. CDN请求过程详解
  9. 常用缓存技巧
  10. 如何高效对接第三方支付
  11. 算法总结

存储

  1. MySQL开发规范
  2. Redis实现分布式锁
  3. 事务原子性、一致性、持久性的实现原理
  4. InnoDB锁与事务简析

网络

  1. HTTP2.0基础教程
  2. HTTPS配置实战
  3. HTTPS连接过程
  4. TCP性能优化

工具

  1. 根据mysql表自动生成go struct
  2. Markdown编辑器推荐-typora

读书笔记

  1. 原则
  2. 资治通鉴
  3. 敏捷革命
  4. 如何锻炼自己的记忆力
  5. 简单的逻辑学-读后感
  6. 热风-读后感
  7. 论语-读后感
  8. 孙子兵法-读后感

思考

  1. 为动员一切力量争取抗战胜利而斗争
  2. 反对自由主义
  3. 实践论
  4. 评价自己的标准
  5. 服务端团队假期值班方案
  6. 项目流程管理
  7. 对项目管理的一些看法
  8. 对产品经理的一些思考
  9. 关于程序员职业发展的思考
  10. 关于代码review的思考
相关文章
|
4月前
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
164 15
|
11月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
87 2
|
5月前
|
设计模式 存储 安全
设计模式-单例模式练习
单例模式是Java设计模式中的重要概念,确保一个类只有一个实例并提供全局访问点。本文详解单例模式的核心思想、实现方式及线程安全问题,包括基础实现(双重检查锁)、懒汉式与饿汉式对比,以及枚举实现的优势。通过代码示例和类图,深入探讨不同场景下的单例应用,如线程安全、防止反射攻击和序列化破坏等,展示枚举实现的简洁与可靠性。
108 0
|
6月前
|
设计模式 安全 Java
设计模式:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数、自行创建实例和静态方法(如`getInstance()`)实现。适用于数据库连接池、日志管理器等需要全局唯一对象的场景。常见的实现方式包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举。线程安全问题可通过`synchronized`或双重检查锁解决,同时需防止反射和序列化破坏单例。优点是避免资源浪费,缺点是可能增加代码耦合度和测试难度。实际开发中应优先选择枚举或静态内部类,避免滥用单例,并结合依赖注入框架优化使用。
|
7月前
|
设计模式 存储 安全
设计模式2:单例模式
单例模式是一种创建型模式,确保一个类只有一个实例,并提供全局访问点。分为懒汉式和饿汉式: - **懒汉式**:延迟加载,首次调用时创建实例,线程安全通过双重检查锁(double check locking)实现,使用`volatile`防止指令重排序。 - **饿汉式**:类加载时即创建实例,线程安全但可能浪费内存。 示例代码展示了如何使用Java实现这两种模式。
119 4
|
9月前
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
360 13
|
9月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
109 2
|
10月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
139 4
|
10月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
10月前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
109 1