单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点
实现 声名一个变量,在第一次创建对象的时候返回该对象并将该对象赋值给该变量,下次实例化对象时判断该变量如果不为 null/nil 则直接返回该变量存储的对象
Golang
第一种方式(多线程下不安全,可能会创建多个对象)
package main
import "fmt"
type Config struct{
Host string
Port int
}
var config *Config
func getConfig() *Config {
if config == nil {
config = &Config{
Host: "127.0.0.1",
Port: 3306,
}
return config
}
return config
}
func main() {
c1 := getConfig()
c2 := getConfig()
fmt.Println(c1==c2)
}
第二种方式,加锁(性能稍有影响,因为每次都要加锁)
package main
import (
"fmt"
"sync"
)
type Config struct{
Host string
Port int
}
var config *Config
var mu sync.Mutex
func getConfig() *Config {
mu.Lock()
defer mu.Unlock()
if config == nil {
config = &Config{
Host: "127.0.0.1",
Port: 3306,
}
return config
}
return config
}
func main() {
c1 := getConfig()
c2 := getConfig()
fmt.Println(c1==c2)
}
第三种方式 sync.Once, 推荐使用
package main
import (
"fmt"
"sync"
)
type Config struct{
Host string
Port int
}
var config *Config
var once sync.Once
func getConfig() *Config {
once.Do(func() {
config = &Config{
Host: "127.0.0.1",
Port: 3306,
}
})
return config
}
func main() {
c1 := getConfig()
c2 := getConfig()
fmt.Println(c1==c2)
}
Python
python 要求的单例模式 __init__ 方法里的逻辑也只能调用一次,只需要加个 __flag 判断一下就好
class Server:
__instance = None
__flag = False
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__new__(cls)
return cls.__instance
def __init__(self):
if not self.__flag:
print('exec init')
Server.__flag = True
s1 = Server()
print(s1)
s2 = Server()
print(s2)
print(s1 == s2)