Python:设计模式之单例模式

简介: 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._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
"""

二、懒汉式实例化

实际对象创建发生在 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
"""

三、单态模式 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'}
"""

四、基于元类的单例

元类控制类的实例化

# -*- 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>
"""

五、单例模式应用一

对数据库进行同步操作

# -*- 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>
"""

六、单例模式应用二

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

# -*- 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、Borg或Monostate单态模式允许创建共享相同状态的多个对象

4、单例模式可应用于多个服务间,实现一致的数据库操作


参考:

python设计模式第2版》第二章 单例设计模式

相关文章
|
设计模式 监控 数据库
Python:设计模式之单例模式
Python:设计模式之单例模式
66 0
|
设计模式 Python
Python:设计模式之工厂模式
工厂: 表示负责创建其他类型对象的类
82 0
|
设计模式 算法 Python
Python:设计模式之模板模式
Python:设计模式之模板模式
68 0
|
设计模式 存储 测试技术
Python 设计模式:单例模式
单例模式可能是最简单的设计模式,单例是非常通用的对象。让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
|
设计模式 程序员 Python
Python 实现设计模式之工厂模式
设计模式是可重复使用的编程方案,已被用于各种现实世界的环境中,并被证明能产生预期的结果。在本文中,我们将学习最常见的设计模式之一:工厂模式。
|
设计模式 存储 Python
Python 设计模式:原型模式
原型模式(Prototype Pattern)是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。原型模式能够让我们利用克隆技术在现有对象的基础上创建对象。
Python 设计模式:原型模式
cxa
|
Python
python设计模式之单例模式(二)
上次我们简单了解了一下什么是单例模式,今天我们继续探究。 上次的内容点这 上次们讨论的是GoF的单例设计模式,该模式是指:一个类有且只有一个对象。通常我们需要的是让实例共享一个相同的装态 比如数据库连接。
cxa
3761 0
cxa
|
Python 设计模式 C#
python设计模式之单例模式(一)
单例设计模式的概念: 单例设计模式即确保类有且只有一个特定类型的对象,并提供全局访问点。一般我们操作数据库的时候为了避免统一资源产生互相冲突,创建单例模式可以维护数据的唯一性。 单例模式的特性: 确保类有且只有一个对象被创建。
cxa
1438 0
|
监控 数据库 Python
python设计模式(四):单例模式及创建型模式总结
单例,顾名思义是一个实例,即在一个项目之中,单例的类只实例化一次。它常常应用于数据库操作、日志函数。 在一个大型项目中使用到日志和数据库操作的地方很多,不能每个文件都去单独实例化一次,此时单例模式就显示出了他的价值。
1182 0
|
存储 Python
python设计模式(十):享元模式
元,可理解为python中的元类、最小粒度的类,系统中存在大量的相似对象时,可以选择享元模式提高资源利用率。 # -*- coding:utf-8 -*-class FlyweightBase:     def offer(self):         """享元基类"""         pas...
1202 0