Python:设计模式之单例模式

举报
彭世瑜 发表于 2021/08/14 01:00:56 2021/08/14
【摘要】 单例模式: 1、确保类有且只有一个对象被创建 2、为对象提供一个全局访问点 3、控制共享资源的并行访问 实现单例最简单的方式: 使构造函数私有化,并创建一个静态方法来完成对象初始化 使用场景: 一个类要求只有一个实例对象 单例模式的缺点 1、全局变量可能被误修改 2、对同一个对象创建多个引用 3、所有依赖于全局变量的类都会由于一个类的改变而紧密耦合为全局数据,从而...

单例模式:
1、确保类有且只有一个对象被创建
2、为对象提供一个全局访问点
3、控制共享资源的并行访问

实现单例最简单的方式:
使构造函数私有化,并创建一个静态方法来完成对象初始化

使用场景:
一个类要求只有一个实例对象

单例模式的缺点
1、全局变量可能被误修改
2、对同一个对象创建多个引用
3、所有依赖于全局变量的类都会由于一个类的改变而紧密耦合为全局数据,从而可能在无意中影响另一个类

一、经典的单例模式

只允许Singleton类生成一个实例

# -*- coding: utf-8 -*-


class Singleton(object): def __new__(cls): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance


if __name__ == '__main__': s1 = Singleton() s2 = Singleton() print(s1) print(s2) print(s1 == s2) print(s1 is s2)
"""
<__main__.Singleton object at 0x1021d58d0>
<__main__.Singleton object at 0x1021d58d0>
True
True
"""


  
 
  • 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

二、懒汉式实例化

实际对象创建发生在 get_instance()

# -*- coding: utf-8 -*-


class Singleton(object): __instance = None def __init__(self): if not Singleton.__instance: print("create...") else: print("already exist...") @classmethod def get_instance(cls): if not cls.__instance: cls.__instance = Singleton() return cls.__instance


if __name__ == '__main__': s1 = Singleton.get_instance()  # 实例化 s2 = Singleton.get_instance()  # 已存在,不会实例化 print(s1) print(s2) print(s1 == s2) print(s1 is s2)
"""
create...
<__main__.Singleton object at 0x101ad5860>
<__main__.Singleton object at 0x101ad5860>
True
True
"""


  
 
  • 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

三、单态模式 Monostate

所有对象共享相同的状态

# -*- coding: utf-8 -*-


class Borg(object): __data = {"age": 23} def __init__(self): self.__dict__ = self.__data


if __name__ == '__main__': b1 = Borg() b2 = Borg() # b1 和 b2是不同的对象,共享了相同的属性 print(b1) print(b2) # 修改b1对象, b2对象的属性也变化了 b1.name = "Tom" print(b1.__dict__) print(b2.__dict__)

"""
<__main__.Borg object at 0x102345f60>
<__main__.Borg object at 0x1023452e8>
{'age': 23, 'name': 'Tom'}
{'age': 23, 'name': 'Tom'}
"""

  
 
  • 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

四、基于元类的单例

元类控制类的实例化

# -*- coding: utf-8 -*-


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


if __name__ == '__main__': logger1 = Logger() logger2 = Logger() print(logger1) print(logger2)

"""
<__main__.Logger object at 0x1013658d0>
<__main__.Logger object at 0x1013658d0>
"""

  
 
  • 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

五、单例模式应用一

对数据库进行同步操作

# -*- coding: utf-8 -*-

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]


import sqlite3


class Database(metaclass=MetaSingleton): connection = None def __init__(self, db_url): self.db_url = db_url def get_cursor(self): if self.connection is None: self.connection = sqlite3.connect(self.db_url) self.cursor = self.connection.cursor() return self.cursor


if __name__ == '__main__': db_url = "db.sqlite3" cursor1 = Database(db_url).get_cursor() cursor2 = Database(db_url).get_cursor() print(cursor1) print(cursor2)
"""
<sqlite3.Cursor object at 0x101b4c490>
<sqlite3.Cursor object at 0x101b4c490>
"""


  
 
  • 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
  • 37
  • 38
  • 39
  • 40

六、单例模式应用二

监控服务器,共享服务器数据

# -*- coding: utf-8 -*-


class HealthCheck(object): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(HealthCheck, cls).__new__(cls, *args, **kwargs) return cls._instance def __init__(self): self.servers = [] def add_server(self, server): self.servers.append(server) def pop_server(self): return self.servers.pop() def show_server(self): print("*" * 10) for server in self.servers: print(server) print("*" * 10)


if __name__ == '__main__': h1 = HealthCheck() h2 = HealthCheck() h1.add_server("server1") h1.add_server("server2") h1.add_server("server3") h2.pop_server() h2.show_server() """ ********** server1 server2 ********** """

  
 
  • 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
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

总结

1、当要求一个类只有一个对象时,就可以使用单例模式
2、经典单例模式,允许多次实例化,但返回同一个对象
3、Borg或Monostate单态模式允许创建共享相同状态的多个对象
4、单例模式可应用于多个服务间,实现一致的数据库操作

参考:
《python设计模式第2版》第二章 单例设计模式

文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。

原文链接:pengshiyu.blog.csdn.net/article/details/91493462

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。