设计模式2:单例模式

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

应用场景如:

  1. 配置文件管理器:在一个应用程序中,通常会有一些全局的配置信息需要被读取和管理,这些配置信息只需要被读取一次,而且希望能够在整个应用程序中共享。这时候,单例模式就非常适合用来管理这些配置信息。
  2. 日志记录器:在一个应用程序中,通常需要记录一些日志信息,这些日志信息需要被记录到同一个文件中,而且希望能够在整个应用程序中共享。这时候,单例模式就非常适合用来管理这些日志信息。
  3. 数据库连接池:在一个应用程序中,通常需要连接到数据库来读取和写入数据,这些数据库连接需要被管理和共享。这时候,单例模式就非常适合用来管理这些数据库连接。
  4. 线程池:在一个应用程序中,通常需要创建和管理多个线程来处理任务,而且希望能够在整个应用程序中共享这些线程。这时候,单例模式就非常适合用来管理这些线程。

示例

示例1

package main

import (
	"fmt"
	"sync"
)

type singleton struct{}

var instance *singleton

var once sync.Once

func GetInstance() *singleton {
	once.Do(func() {
		instance = &singleton{}
	})

	return instance
}

func main() {
	instance1 := GetInstance()
	instance2 := GetInstance()

	if instance1 != instance2 {
		fmt.Println("Instances are not the same!")
	} else {
		fmt.Println("Instances are the same!")
	}
}

示例2

package main

import (
    "fmt"
    "sync"
)

type ThreadPool struct {
    maxWorkers int
    queue      chan func()
    once       sync.Once
}

var instance *ThreadPool

func GetInstance() *ThreadPool {
    if instance == nil {
        instance = &ThreadPool{}
        instance.once.Do(func() {
            instance.maxWorkers = 10
            instance.queue = make(chan func(), 100)
            for i := 0; i < instance.maxWorkers; i++ {
                go instance.worker()
            }
        })
    }
    return instance
}

func (tp *ThreadPool) worker() {
    for f := range tp.queue {
        f()
    }
}

func (tp *ThreadPool) AddTask(f func()) {
    tp.queue <- f
}

func main() {
    tp := GetInstance()

    for i := 0; i < 100; i++ {
        tp.AddTask(func() {
            fmt.Println("Hello, world!")
        })
    }
}