GO设计模式——单例模式

从今天开始,学习go语言的设计模式,之前学习java的时候,都没有好好学习一下设计模式,现在从go语言开始把24种常见设计模式从头到尾学习一遍。

单例模式简介

单例模式用于确保一个类只有一个实例,并提供一个全局访问点来获取该实例,但是go语言中没有类的概念,而是用的结构体,以下讲的所有都是基于go语言来讲的。在单例模式下,保证了这个结构体只能被初始化一次。单例模式又分为饿汉模式和懒汉模式,这两种模式的根本区别就是实例的初始化时机。

1、饿汉模式
在包被导入的时候,就初始化了这个结构体的实例。

package singleton

type Singleton struct{
    Name string
}
var singleton = &Singleton{Name:"张三"}

func GetInstance() *Singleton{
    return singleton
}

2、懒汉模式
在第一次需要使用这个结构体的实例的时候,这个实例才被初始化。

package singleton
import (
    "sync"
)
type Singleton struct{
    Name string
}

var singleton *Singleton
//使用sync.Once来确保线程安全
var once sync.Once
func GetInstance() *Singleton{
    once.Go(func (){
        singleton = &Singleton{Name:"张三"}
    })
    return singleton
}

sync.Once只提供一个Do方法,这个方法只会执行一次。让我们来试一试:

package main
import(
    "sync"
    "fmt"
)
type Singleton struct{
    Name string
}

var singleton *Singleton
//使用sync.Once来确保线程安全
var once sync.Once

func GetInstance() *Singleton{
    fmt.Println("进入到函数,在once.Go外面执行")
    once.Do(func (){
        fmt.Println("进入到once.Go里面执行")
        singleton = &Singleton{Name:"张三"}
    })
    return singleton
}

func main(){
    ins1 := GetInstance()
    ins2 := GetInstance()
    fmt.Println(ins1)
    fmt.Println(ins2)
}

//输出:
//进入到函数,在once.Go外面执行
//进入到once.Go里面执行
//进入到函数,在once.Go外面执行
//&{张三}                         
//&{张三} 

我们可以看到,在调用了两次GetInstance函数后,once.Do方法只执行了一次。

练手题目

这里我们使用的题目都来自于代码随想录的卡码网,大家也可以自己去上面练习。

题目简介:

【设计模式专题之单例模式】1.小明的购物车
时间限制:1.000S  空间限制:256MB
题目描述
>小明去了一家大型商场,拿到了一个购物车,并开始购物。请你设计一个购物车管理器,记录商品添加到购物车的信息(商品名称和购买数量),并在购买结束后打印出商品清单。(在整个购物过程中,小明只有一个购物车实例存在)。

输入描述
>输入包含若干行,每行包含两部分信息,分别是商品名称和购买数量。商品名称和购买数量之间用空格隔开。

输出描述
>输出包含小明购物车中的所有商品及其购买数量。每行输出一种商品的信息,格式为 "商品名称 购买数量"。

输入示例
>Apple 3  
>Banana 2  
>Orange 5  

输出示例
>Apple 3  
>Banana 2  
>Orange 5  

提示信息
>本道题目请使用单例设计模式:
>使用私有静态变量来保存购物车实例。
>使用私有构造函数防止外部直接实例化。

代码比较简单,使用懒汉式。直接上代码:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
    "sync"
)

type ShoppingCar struct {
    Product []string
    Numb    []int
}

var shoppingCar *ShoppingCar
var once sync.Once

func getInstance() *ShoppingCar {
    once.Do(func() {
       shoppingCar = &ShoppingCar{Product: []string{}, Numb: []int{}}
    })
    return shoppingCar
}

func main() {
    ins1 := getInstance()
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
       text := scanner.Text()
       if text == "done" {
          break
       }
       //将输入按空格分割为字符串切片,split[0]是商品名称,split[1]是购买数量
       split := strings.Split(text, " ")
       numb, _ := strconv.Atoi(split[1])
       ins1.Product = append(ins1.Product, split[0])
       ins1.Numb = append(ins1.Numb, numb)
    }
    for index, _ := range ins1.Product {
       fmt.Printf("%s %d \n", ins1.Product[index], ins1.Numb[index])
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值