单态模式及其应用

1.什么是单态?

单态,也即单例模式,是设计模式之一。通过单例模式,所编写的类保证只有一个实例对象,多用于一个项目中配置信息等,当在多处进行引用时无论实例化多少次配置的类都只有一个实例化对象,从而减少内存的浪费。

2.几种单态的写法

2.1模块导入的方式

当我们定义了一个类之后,进行实例化,这样其他需要引用的地方直接导入该实例化对象进行引用,这样实例化的对象是唯一的。python的模块导入即是这样单例模式,一次导入就会生成.py文件,当再次导入时就会加载该文件。

class Singleton():
    def env_name(self, name):
        print('this time is in the env:{}'.format(name))

singleton_obj = Singleton()

在其他文件中直接引入实例化对象single_obj

from singleton import singleton_obj
singleton_obj.env_name("dev")

2.2使用装饰器实现

# 装饰器单例模式
def singleton(cls):
    _dict = {}
    
    def _singleton(*args, **kwargs):
        if cls not in _dict:
            _dict[cls] = cls(*args, **kwargs)
        return _dict[cls]
    return _singleton


@singleton
class Sample():
    def __init__(self, param):
        self.param = param


if __name__ == "__main__":
    a = Sample(23)
    b = Sample(34)
    print(a.param)
    print(b.param)
    print( id(a), id(b))

执行结果为:
在这里插入图片描述
可以看出即使进行了多次实例化该对象是同一个。

2.3 使用类来写单例

# 使用类写单例
class Singleton(object):
    def __init__(self, usage):
        self.usage = usage

    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            Singleton._instance = Singleton(*args, **kwargs)
        return Singleton._instance
if __name__ == "__main__":
	singleton_obj1 = Singleton.instance('用于单例测试1')
	singleton_obj2 = Singleton.instance('用于单例测试2')
	print(singleton_obj1.usage)
	print(singleton_obj2.usage)

代码执行结果:
在这里插入图片描述

2.4支持多线程

以上写的单例示例并不能支持多线程,解决办法是加锁,通过串行方式虽降低了效率但保证了数据安全。

# 支持多线程
import threading
class Singleton(object):
    _instance_lock = threading.Lock()

    def __init__(self, usage):
        time.sleep(1)
        self.usage = usage
        print(self.usage)

    @classmethod
    def instance(cls, *args, **kwargs):
       if not hasattr(cls, '_instance'):
            with Singleton._instance_lock:
                if not hasattr(cls, '_instance'):
                    Singleton._instance = Singleton(*args, **kwargs)
       return Singleton._instance

def test(num):
    print(Singleton.instance(num))

if __name__ == "__main__":
    for i in range(10):
        t = threading.Thread(target=test, args=(i,))
        t.start()

执行结果:
在这里插入图片描述
可以看出在多线程当中需要在单例中加锁才能确保其实例化对象的唯一性。

2.5基于__new__来实现(常用)

通过以上方法实现的单例需要通过调用类中的方法instance来进行实现,而使用__new__方法来进行构造是在创建对象的时候进行控制从而实现单例模式,直接实例化obj = Singleton()即可,而无需再调用任何方法。

import threading
class Singleton(object):
    _instance_lock = threading.Lock()

    def __init__(self, usage):
        time.sleep(1)
        self.usage = usage
        print(self.usage)

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with Singleton._instance_lock:
                if not hasattr(cls, '_instance'):
                    Singleton._instance = object.__new__(cls)
        return Singleton._instance

3.单态的应用

项目的配置信息对象使用单态,然就进行环境配置信息初始化。

class Singleton(object):
    _instance_lock = threading.Lock()

    def __init__(self):

        self.g_dict = {}
        self.is_init = False

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with Singleton._instance_lock:
                if not hasattr(cls, '_instance'):
                    Singleton._instance = super().__new__(cls)
        return Singleton._instance


single_obj = Singleton()


def global_init():
    """
    全局变量初始化
    """
    global _config_dict
    _config_dict = single_obj.g_dict


def set_globle_value(**kwargs):
    """
    设置全局变量
    :param kwargs:{key: value}形式
    """
    _config_dict.update(kwargs)


def get_globle_value(name, default=None):
    """
    根据指定字段获取全局变量
    :return:
    """
    try:
        return _config_dict.get(name)
    except KeyError:
        return None


def get_globle_keys():
    return _config_dict.keys()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值