【编程学习】单例模式-打造代码的优雅之道

写在前面

这是我第一次分享设计模式相关的知识,因此先给大家介绍一下什么是设计模式。

所谓设计模式,就是为了让代码拥有更好的可读性、可拓展性以及可靠性的代码编写方式。

设计模式的使用有几个原则:

  • 开闭原则(Open Close Principle)
    • 对扩展开放,对修改关闭
  • 里氏代换原则(Liskov Substitution Principle)
    • 任何基类可以出现的地方,派生类一定可以出现
    • 即基类可被派生类替换
  • 依赖倒转原则(Dependence Inversion Principle)
    • 针对接口编程,依赖抽象而不依赖具体
  • 接口隔离原则(Interface Segregation Principle)
    • 使用多个隔离的接口,比使用单个接口要好
    • 降低类之间的耦合度
  • 最小知道原则(Demeter Principle)
    • 一个实体应当尽量少地与其他实体发生作用
    • 系统功能模块应相对独立
  • 合成复用原则(Composite Reuse Principle)
    • 尽量使用合成/聚合的方式,而不是使用继承

单例模式

单例模式,顾名思义,就是全局只有一个一个实例的设计模式,通常在设计全局配置参数时使用。

简单来说就是不管你实例化多少个类,他最终指向的都是同一个实例。具体到Python层面,就是通过给类添加一一个_instance属性,并通过__new__方法判断_instance属性的取值,并在该类没有实例化时新建一个类,在之前实例化过时修改先前实例化的结果。

1
2
3
4
5
6
7
8
9
10
11
12
class Singleton:
_instance=None # 首次实例化的信息

def __init__(self, name, volume):
self.name=name
self.volume=volume

def __new__(cls,name,volume):
if Singleton._instance==None: # 如果没实例化过,实例化
Singleton._instance=object.__new__(cls)
Singleton.__init__(Singleton._instance,name,volume)
return Singleton._instance

我们实例化两个Singleton类看看结果,可以看到,尽管我们先后实例化了两个Singleton,但是,实例化第二个类以后,输出的两个类属性与都是第二次实例化设置的属性,而且实例的地址没有发生改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a = Singleton('a',101)
print(hex(id(a)),end='\t')
print("{}\t{}".format(a.name,a.volume))

# output:
# 0x2226870efe0 a 101


b = Singleton('b',111)
print(hex(id(a)),end='\t')
print("{}\t{}".format(a.name,a.volume))
print(hex(id(b)),end='\t')
print("{}\t{}".format(b.name,b.volume))

# output:
# 0x2226870efe0 b 111
# 0x2226870efe0 b 111

需要注意的是,这种方式构建的单例模式在多线程的应用场景下不安全,可能因为线程之间的通信问题创建出多个实例。