什么是单例模式?
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
实现
var (
p *Pet
once sync.Once
)
func GetInstance() *Pet {
return p
}
func init() {
once.Do(func() {
p = &Pet{}
})
}
type Pet struct {
name string
age int
mux sync.Mutex
}
func (this *Pet)SetName(name string) {
this.mux.Lock()
defer this.mux.Unlock()
this.name = name
}
func (this *Pet)GetName() string {
this.mux.Lock()
defer this.mux.Unlock()
return this.name
}
func (this *Pet)SetAge(age int) {
this.mux.Lock()
defer this.mux.Unlock()
this.age = age
}
func (this *Pet)GetAge() int {
this.mux.Lock()
defer this.mux.Unlock()
return this.age
}
func (this *Pet)IncrementAge() {
this.mux.Lock()
defer this.mux.Unlock()
this.age++
}
func TestGetInstance(t *testing.T) {
p := GetInstance()
p.SetAge(10)
p.IncrementAge()
fmt.Println("p 的 Age现在是", p.GetAge())
q := GetInstance()
q.IncrementAge()
fmt.Println("q 的 Age现在是", q.GetAge())
}
/*
=== RUN TestGetInstance
p 的 Age现在是 11
q 的 Age现在是 12
--- PASS: TestGetInstance (0.00s)
PASS
*/
优点
- 内存中只有一个实例,减少了内存开支,尤其一个对象需要频繁地创建销毁,而此时性能又无法优化时,单例模式的优势就非常明显;
- 避免对资源的多重占用(比如写文件操作,只有一个实例时,避免对同一个资源文件同时写操作),简单来说就是对唯一实例的受控访问。
缺点
- 没有接口,不能继承,与单一职责冲突。
使用场景
- 要求生成唯一序列号的环境;
- 在整个项目中有一个共享访问点或共享数据(如web页面上的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来即可);
- 创建一个对象需要消耗的资源过多时(如访问I/O和数据库等资源)。
网友评论