【设计模式】单例模式

您所在的位置:网站首页 几种线程池设计模式 【设计模式】单例模式

【设计模式】单例模式

2024-07-16 15:09| 来源: 网络整理| 查看: 265

文章目录 一、单例模式概念二、应用场景三、实现核心原理四、单例模式代码实现方式4.1 使用模块4.2 使用装饰器4.3 懒汉式 非线程安全的单例模式4.4 懒汉式 线程安全的单例

一、单例模式概念

单例模式(Singleton Pattern) 是最简单的设计模式之一,属于创建型模式。它提供了一种创建对象的最佳方式。

单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1、单例类只能有一个实例。2、单例类必须自己创建自己的唯一实例。3、单例类必须给所有其他对象提供这一实例。每一次执行 类名() 返回的对象,内存地址是相同

优点:

1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。2、避免对资源的多重占用(比如写文件操作)。

缺点: 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

二、应用场景

资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如日志文件,应用配置。

控制资源的情况下,方便资源之间的互相通信。如线程池等。

网站的计数器 不用每次刷新都在数据库里加一次,用单例先缓存起来。 应用配置 多线程池 数据库配置,数据库连接池 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。 应用程序的日志应用 要求生产唯一序列号 音乐播放 对象 回收站 对象 打印机 对象

三、实现核心原理

重写类方法中的__new__方法

使用 类名() 创建对象时,Python 的解释器 首先 会 调用 __new__ 方法为对象 分配空间__new__ 是一个 由 object 基类提供的 内置的静态方法,主要作用有两个: 在内存中为对象 分配空间 返回 对象的引用 Python 的解释器获得对象的 引用 后,将引用作为 第一个参数,传递给 __init__ 方法

重写 __new__ 方法 的代码非常固定!

重写 __new__ 方法 一定要 return super().__new__(cls)否则 Python 的解释器 得不到 分配了空间的 对象引用,就不会调用对象的初始化方法注意:__new__ 是一个静态方法,在调用时需要 主动传递 cls 参数 四、单例模式代码实现方式 4.1 使用模块

Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

# mysingleton.py class Singleton(object): def foo(self): pass singleton = Singleton()

将上面的代码保存在文件 mysingleton.py 中,要使用时,直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象

from a import singleton 4.2 使用装饰器 def Singleton(cls): _instance = {} def _singleton(*args, **kargs): if cls not in _instance: _instance[cls] = cls(*args, **kargs) return _instance[cls] return _singleton @Singleton class Test(object): t = 1 def __init__(self, x=0): self.x = x t1 = Test(2) t2 = Test(3) 4.3 懒汉式 非线程安全的单例模式

**描述:**这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。 这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

class Singleton(object): __instance = None def __new__(cls, name, age): # 如果类属性__instance的值为None,那么就创建一个对象 if not cls.__instance: cls.__instance = object.__new__(cls) # 如果已经有实例存在,直接返回 return cls.__instance a = Singleton("Zhangsan", 18) b = Singleton("lisi", 20) print(id(a)) print(id(b)) a.age = 30 # 给a指向的对象添加一个属性 print(b.age) # 获取b指向的对象的age属性 4.4 懒汉式 线程安全的单例

**描述:**这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。 优点:第一次调用才初始化,避免内存浪费。 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。

import threading """ 线程安全的单利模式 紧跟with后面的语句被求值后,返回对象的 __enter__() 方法被调用,这个方法的返回值将被赋值给as后面的变量。 当with后面的代码块全部被执行完之后,将调用前面返回对象的 __exit__()方法 """ def synchronized(func): func.__lock__ = threading.Lock() def lock_func(*args, **kwargs): with func.__lock__: return func(*args, **kwargs) return lock_func class Singleton(object): instance = None @synchronized def __new__(cls): # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象 if not cls.instance: cls.instance = super(Singleton, cls).__new__(cls) return cls.instance


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3