设计模式笔记 - 单例模式

145 阅读2分钟

单例模式是一种创建型设计模式,让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。


实现单例模式需要一下两步:

  • 将默认构造函数设为私有, 防止其他对象创建对象的实例。
  • 新建一个静态构建方法作为构造函数,用于生成对象。此后所有对于该函数的调用都将返回这一缓存对象。

优点:

  • 你可以保证一个类只有一个实例

  • 你获得了一个指向该实例的全局访问节点

  • 仅在首次请求单例对象时对其进行初始化


缺点:

  • 违反了单一职责原则。 同时解决了两个问题:保证一个类只有一个实例为该实例提供一个全局访问节点
  • 单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等
  • 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象
  • 单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象

实例代码:

package main

import (
	"sync"
	"sync/atomic"
)

type singleton struct {
	num int32
}

var slton *singleton = nil
var mutex sync.Mutex

func getSingleton() *singleton {
	if slton != nil {
		return slton
	}

	mutex.Lock()
	defer mutex.Unlock()
	return &singleton{num: 0}
}

func (s *singleton) getNum() int32 {
	return atomic.LoadInt32(&s.num)
}

func (s *singleton) setNum(num int32) int32 {
	return atomic.SwapInt32(&s.num, num)
}

func main() {
	ch := make(chan int32, 100)
	var w sync.WaitGroup

	for i := 0; i < 100; i++ {
        w.Add(1)
		go func(i int32) {
			s := getSingleton()
			s.setNum(i)

			ch <- s.getNum()
            if len(ch) == 100 {
                close(ch)
            }

			w.Done()
		}(int32(i))
	}

	w.Wait()
    for _ = range ch { }
}

参考