20·Python基础-单例模式四种实现方式

2022-09-26 12:33:20 浏览数 (1)

  • 单例模式介绍
  • 实现单例模式的第一种方式
  • 实现单例模式的第二种方式
  • 实现单例模式的第三种方式
  • 实现单例模式的第四种方式

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


单例模式介绍


什么是单例模式

单例模式:多次实例化的结果指向同一个实例

是面向对象的一种设计模式


举例

代码语言:javascript复制
class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

# 第一次实例化
obj1=MySQL('1.1.1.1',3306)

# 再一次实例化,又得到一个容器
obj2=MySQL('1.1.1.1',3306)

# 第三次实例化
obj3=MySQL('1.1.1.1',3306)

## 我们经过三次实例化会发现,会产生3个内存地址,这三个内存地址存储的数据都是一样的,所以我们没有必要存储那么多次。

## 所以单例模式的作用,就是把结果指向一个实例,如此一来,我们就可以做到节省资源

## 例如我们之前实现 过的,使用settings.py文件来存储数据,然后导入 

### settings.py
IP='1.1.1.1'
PORT=3306

### 导入settings.py文件
import settings

class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

obj1=MySQL(settings.IP, settings.PORT)
obj2=MySQL(settings.IP, settings.PORT)
obj3=MySQL(settings.IP, settings.PORT)

实现单例模式的第一种方式

代码语言:javascript复制
import settings

class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod
    def from_conf(cls):
        return cls(settings.IP,settings.PORT)

obj1=MySQL.from_conf()
obj2=MySQL.from_conf()
obj3=MySQL.from_conf()
print(obj1)
print(obj2)
print(obj3)
# 比原来精简了,但是没有实现单例
import settings

class MySQL:
    __instance=None
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod
    def from_conf(cls):
        if cls.__instance is None:
            cls.__instance=cls(settings.IP, settings.PORT)
        return cls.__instance
obj1=MySQL.from_conf()
obj2=MySQL.from_conf()
obj3=MySQL.from_conf()

obj4=MySQL('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

实现单例模式的第二种方式

使用装饰器来实现

代码语言:javascript复制
import settings

def singleton(cls):
    def wrapper(*args,**kwargs):
        instance=cls(*args,**kwargs)
        return instance
    return wrapper

@singleton #MySQL=singleton(MySQL) #MySQL=wrapper
class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

obj=MySQL('1.1.1.1',3306) #obj=wrapper('1.1.1.1',3306)
print(obj.__dict__)
## 目前装饰器 ,什么功能都没有实现,我们要定制,MySQL内不传递任何参数就返回已经定义好的对象


import settings

def singleton(cls):
    _instance=cls(settings.IP,settings.PORT)
    def wrapper(*args,**kwargs):
        if len(args) !=0 or len(kwargs) !=0:
            obj=cls(*args,**kwargs)
            return obj
        return _instance
    return wrapper

@singleton #MySQL=singleton(MySQL) #MySQL=wrapper
class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

obj1=MySQL() #wrapper()
obj2=MySQL() #wrapper()
obj3=MySQL() #wrapper()
obj4=MySQL('1.1.1.3',3302) #wrapper('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

实现单例模式的第三种方式

使用元类来实现单例模式

代码语言:javascript复制
import settings

class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        #self=MySQL这个类
        self.__instance=self(settings.IP,settings.PORT)

    def __call__(self, *args, **kwargs):
        # self=MySQL这个类
        if len(args) != 0 or len(kwargs) != 0:
            obj=self.__new__(self)
            self.__init__(obj,*args, **kwargs)
            return obj
        else:
            return self.__instance

class MySQL(metaclass=Mymeta): #MySQL=Mymeta(...)
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

obj1=MySQL()
obj2=MySQL()
obj3=MySQL()
obj4=MySQL('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

实现单例模式的第四种方式

使用导入模块的方式

settings.py

代码语言:javascript复制
IP='1.1.1.1'
PORT=3306

singleton.py

代码语言:javascript复制
import settings

class MySQL:
    print('run....')
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

instance=MySQL(settings.IP,settings.PORT)

导入singleton模块并调用

代码语言:javascript复制
def f1():
    from singleton import instance
    print(instance)

def f2():
    from singleton import instance,MySQL
    print(instance)
    obj=MySQL('1.1.1.3',3302)
    print(obj)

f1()
f2()

0 人点赞