Python:设计模式之单例模式

单例模式:
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._instanceif __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
"""

二、懒汉式实例化

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

# -*- coding: utf-8 -*-class Singleton(object):__instance = Nonedef __init__(self):if not Singleton.__instance:print("create...")else:print("already exist...")@classmethoddef get_instance(cls):if not cls.__instance:cls.__instance = Singleton()return cls.__instanceif __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
"""

三、单态模式 Monostate

所有对象共享相同的状态

# -*- coding: utf-8 -*-class Borg(object):__data = {"age": 23}def __init__(self):self.__dict__ = self.__dataif __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'}
"""

四、基于元类的单例

元类控制类的实例化

# -*- 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):passif __name__ == '__main__':logger1 = Logger()logger2 = Logger()print(logger1)print(logger2)"""
<__main__.Logger object at 0x1013658d0>
<__main__.Logger object at 0x1013658d0>
"""

五、单例模式应用一

对数据库进行同步操作

# -*- 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 sqlite3class Database(metaclass=MetaSingleton):connection = Nonedef __init__(self, db_url):self.db_url = db_urldef get_cursor(self):if self.connection is None:self.connection = sqlite3.connect(self.db_url)self.cursor = self.connection.cursor()return self.cursorif __name__ == '__main__':db_url = "db.sqlite3"cursor1 = Database(db_url).get_cursor()cursor2 = Database(db_url).get_cursor()print(cursor1)print(cursor2)
"""


"""

六、单例模式应用二

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

# -*- coding: utf-8 -*-class HealthCheck(object):_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super(HealthCheck, cls).__new__(cls, *args, **kwargs)return cls._instancedef __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()"""**********server1server2**********"""

总结

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

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


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部