Python设计模式——单例模式

定义

Singleton provides you with a mechanism to have one, and only one, object of a given type and provides a global point of access.
单例模式常用与logging或者database operations等。他们都只需要一个实例来操作从而避免冲突

UML



实现代码

普通版

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
# coding:utf-8
class Singleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
s = Singleton()
print("Object created", s)
s1 = Singleton()
print("Object created", s1)
Object created <__main__.Singleton object at 0x000001B2A199A630>
Object created <__main__.Singleton object at 0x000001B2A199A630>
#### Lazy instantiation版
class Singleton:
__instance = None
def __init__(self):
if not Singleton.__instance:
print(" __init__ method called..")
else:
print("Instance already created:", self.getInstance())
@classmethod
def getInstance(cls):
if not cls.__instance:
cls.__instance = Singleton()
return cls.__instance
# s = Singleton.getInstance()
# print("Object created", s)
# s1 = Singleton.getInstance()
# print("Object created", s1)

The Monostate Singleton pattern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
'''
单例模式要求每一个类只有一个实例,通常来说,我们更需要的是所有实例都共享同一个状态
Python中使用__dict__去存储对象的所有状态
'''
class Borg:
__shared_state = {"1": "2"}
def __init__(self):
self.x = 1
self.__dict__ = self.__shared_state
pass
# 我们也可以在__new__中调整
class Borg(object):
_shared_state = {}
def __new__(cls, *args, **kwargs):
obj = super(Borg, cls).__new__(cls, *args, **kwargs)
obj.__dict__ = cls._shared_state
return obj
# b = Borg()
# b1 = Borg()
# b.x = 4
# print("Borg Object 'b': ", b) ## b and b1 are distinct objects
# print("Borg Object 'b1': ", b1)
# print("Object State 'b':", b.__dict__) ## b and b1 share same state
# print("Object State 'b1':", b1.__dict__)

单例模式与元类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
'''
元类是类的类(a class of a class),这意味着类是元类的实例
Python里面万物皆对象。
a=5,type(a) 返回 <type 'int'> 意味着 a 是int类型
type(int) 返回 <type 'type'> 意味着 int 是type类型
我们可以用type生成一个类
A = type(name, bases, dict)
name:生成的类名
bases:基类
dict:类的字典,各种属性等
'''
class MetaSingleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Logger(metaclass=MetaSingleton):
pass
# logger1 = Logger()
# logger2 = Logger()
# print(logger1, logger2)

关于元类,可以参考关于Python中的元类(metaclass)

实战

服务器应用就是一个很好的例子
大量的连接只需要一个实例,节省内存
防止冲突

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import sqlite3
class MetaSingleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Database(metaclass=MetaSingleton):
connection = None
def connect(self):
if self.connection is None:
self.connection = sqlite3.connect("db.sqlite3")
self.cursorobj = self.connection.cursor()
return self.cursorobj
db1 = Database().connect()
db2 = Database().connect()
print("Database Objects DB1", db1)
print("Database Objects DB2", db2)

优点

  • 内存中只有一个实例,减少内存开支(Ensuring that one and only one object of the class gets created)
  • 避免资源的多重占用(Controlling concurrent access to resources that are shared)
  • 可以在系统设置全局的访问点(Providing an access point for an object that is global to the program)

缺点

  • 单例模式一般没有接口,扩展很困难。
  • 所有类都依赖于一个实例耦合紧。
  • 与单一性职责原则冲突。

使用场景

  • 要求生成唯一序列号的环境
  • 在整个项目中需要一个共享访问点或共享数据
  • 创建一个对象需要消耗的资源过多
  • 需要定义大量的静态常量和静态方法的环境
  • 在多线程的情况下,单例模式是线程不安全的。必须进行改进。
  • 在Python中所有的模块都是单例的。
  • Python中导入import步骤如下
    • 检查是否已经导入
    • 如果已经导入,返回该模块的实例(object for the module)。如果没有,导入并实例化它(imports and instantiates it)
文章目录
  1. 1. 定义
  2. 2. UML
  3. 3. 实现代码
    1. 3.1. 普通版
    2. 3.2. The Monostate Singleton pattern
    3. 3.3. 单例模式与元类
  4. 4. 实战
  5. 5. 优点
  6. 6. 缺点
  7. 7. 使用场景
|