单例模式其实在实际的程序开发中使用过,比如数据库连接池等,但是仍然需要抽象到一定高度来理解它。

单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点。目的就是令到单个进程中只存在一个类的实例,从而可以实现数据的共享,节省系统开销,防止io阻塞等等。方法就是让类自身保存他的唯一实例,这个类可以保证没有其他实例可以被创建。

多线程时的单例模式:加锁-双重锁定

  • 饿汉式单例类:在类被加载时就将自己实例化(静态初始化)。其优点是躲避了多线程访问的安全性问题,缺点是提前占用系统资源。
  • 懒汉式单例类:在第一次被引用时,才将自己实例化。避免开始时占用系统资源,但是有多线程访问安全性问题。

简单粗暴-模块实现

直接导入某个模块下创建好的实例

1
2
3
4
5
6
7
# some module.py
class SingletonClass:
pass
# 在别处我们想用这个实例都直接使用 module.single_instance 这个实例就好。
# 这是最简单也是最直观的一种方式,嗯,直接导入这个实例用,而不是导入class,简单粗暴
single_instance = SingletonClass()

静态方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#encoding=utf-8
#单例模式
def print_info(info):
print(info)
import threading
#单例类
class Singleton:
instance = None
mutex = threading.Lock()
def __init__(self):
pass
@staticmethod
def get_instance():
if Singleton.instance is None:
Singleton.mutex.acquire()
if Singleton.instance is None:
print_info('初始化实例')
Singleton.instance = Singleton()
else:
print_info('单例已经实例化')
Singleton.mutex.release()
else:
print_info('单例已经实例化')
return Singleton.instance
def clientUI():
Singleton.get_instance()
Singleton.get_instance()
Singleton.get_instance()
if __name__=='__main__':
clientUI();

元类实现

也可以使用__new__来实现单例模式,但是如果需要做到线程安全就必须加锁。__new__必须返回一个类的实例,所以可以在对象创建之前或者之后修改类。如果它返回的不是cls的实例,那么__init__方法是不会调用的。

1
2
3
4
5
6
7
8
9
10
class Singleton(object):
__instance = None
def__new__(cls, *args, **kwd):
if Singleton.__instance is None:
Singleton.__instance = object.__new__(cls, *args, **kwd)
return Singleton.__instance
class MyClass(metaclass=Singleton):
pass

装饰器实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class BaseClass:
pass
# 装饰器实现
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
@singleton
class MyClass(BaseClass):
pass