单例模式的三种实现方式

一、单例模式的三种实现方式

1. 什么是单例模式

  • 基于某种方法,实例化多次,得到同一个实例/对象

2. 为什么用单例模式

  • 实例化多次,得到的对象属性内容都一样时,应该将这些对象指向同一个内存,即同一个实例,来节省内存空间

1. 实现单例模式方式一:类内部定义类方法实现

  • 实现方法:类中定义了一个类方法
# 未单例模式前
import setting
class Mysql:
    def __init__(self,ip,port):
        self.ip=ip
        self.port=port

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

obj1=Mysql.from_conf()
obj2=Mysql.from_conf()
obj3=Mysql.from_conf()

# 内容相同
print(obj1.__dict__)
print(obj2.__dict__)
print(obj3.__dict__)
# 但是占用不同的内存空间,导致内存空间浪费
print(obj1)
print(obj2)
print(obj3)
----------------------------------------------------
{‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306}
{‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306}
{‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306}
<__main__.Mysql object at 0x000001B0F234F588>
<__main__.Mysql object at 0x000001B0F234F5F8>
<__main__.Mysql object at 0x000001B0F234F630>
# setting配置文件
IP=‘10.0.0.1‘
PORT=3306

import setting
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(setting.IP,setting.PORT)
        return cls.__instance

obj1=Mysql.from_conf()
obj2=Mysql.from_conf()
obj3=Mysql.from_conf()

# 内容相同
print(obj1.__dict__)
print(obj2.__dict__)
print(obj3.__dict__)
# 占用相同的内存空间
print(obj1)
print(obj2)
print(obj3)
---------------------------------------------------------------
{‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306}
{‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306}
{‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306}
<__main__.Mysql object at 0x000001A79D29F588>
<__main__.Mysql object at 0x000001A79D29F588>
<__main__.Mysql object at 0x000001A79D29F588>

# 如果ip,port不同,再单独造对象
obj4=Mysql(‘10.0.0.10‘,3307)
print(obj4)
print(obj4.__dict__)
---------------------------------------------------------------
<__main__.Mysql object at 0x0000015D8C13F630>
{‘ip‘: ‘10.0.0.10‘, ‘port‘: 3307}

2. 实现单例模式方式二:利用装饰器实现

  • _intance是一种命名习惯,代表在函数内使用的名字
import setting
def singleton(cls):
    _intance=cls(setting.IP,setting.PORT)
    def wrapper(*args,**kwargs):
        if len(args) == 0 and len(kwargs) == 0:
            return _intance
        return cls(*args,**kwargs)
    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()
obj3=Mysql()
print(obj1 is obj2 is obj3)

print(obj1)
print(obj2)
print(obj3)
-----------------------------------------------------
True
<__main__.Mysql object at 0x000001ED9FBDF588>
<__main__.Mysql object at 0x000001ED9FBDF588>
<__main__.Mysql object at 0x000001ED9FBDF588>

3. 实现单例模式方式三:定制元类实现

import setting
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic): # self=Mysql
        super().__init__(class_name,class_bases,class_dic)
        # 创造一个Mysql的空对象
        self.__instance=self.__new__(self)
        # 从配置文件中获取信息,初始化Mysql的对象
        self.__init__(self.__instance,setting.IP,setting.PORT)

    def __call__(self, *args, **kwargs):   # self=Mysql
        if len(args) == 0 and len(kwargs) == 0:
            return self.__instance   # 返回的是一个已经创建好的Mysql对象
        # 如果在Myql()括号内,单独传入内容,再重新造对象
        obj=self.__new__(self)
        self.__init__(self,*args,**kwargs)
        return obj

class Mysql(object,metaclass=Mymeta):
    def __init__(self,ip,port):
        self.ip=ip
        self.port=port

obj1=Mysql()
obj2=Mysql()
obj3=Mysql()
obj4=Mysql(‘10.0.0.10‘,3307)

print(obj1)
print(obj2)
print(obj3)
print(obj4)
--------------------------------------------------------------------------
<__main__.Mysql object at 0x0000021DBB7FF668>
<__main__.Mysql object at 0x0000021DBB7FF668>
<__main__.Mysql object at 0x0000021DBB7FF668>

<__main__.Mysql object at 0x0000021DBB7FF6A0>

原文地址:https://www.cnblogs.com/itone/p/9253629.html

时间: 2024-10-10 13:48:43

单例模式的三种实现方式的相关文章

设计模式之单例模式(三种实现方式)

一.单例模式要点 1.单例,顾名思义,某个类仅仅能有一个实例. 2.它必须自行创建这个唯一的实例. 3.它必须自行向整个系统提供这个实例. 二.单例模式的三种实现 1.饿汉式单例类(类载入时就初始化) 代码实现 public class EagerSingleton { //私有的类成员常量 private static final EagerSingleton SINGLETON=new EagerSingleton(); //私有的默认构造方法.此类不能被继承 private EagerSi

设计模式:单例模式的三种创建方式及其各自的优缺点

单例模式: 确保一个类仅仅有一个实例,并提供全局訪问点.在Java中实现单例模式须要私有的构造器,一个静态方法和一个静态变量.确定在性能和资源上 的限制,怎样选择适当的方案来实现单例,以解决多线程的问题. 假设使用多个类载入器,可能导致单例失效产生多个实例.双重检查加锁不适用于1.4及更早版本号的java. 方式1: package singleton; /** * 同步getInstance()方法: * 有点:保证线程安全. * 缺点:性能大大下降 * @author Arvon * */

python实现单例模式的三种方式及相关知识解释

python实现单例模式的三种方式及相关知识解释 模块模式 装饰器模式 父类重写new继承 单例模式作为最常用的设计模式,在面试中很可能遇到要求手写.从最近的学习python的经验而言,singleton实现的四种方法都是python的重要特征,反过来也刚好是几种特征的最佳实现.(比如你平常开发中很难遇到几个需要写元类的地方)如果不能随手写出某种实现,说明你对于那种实现的概念还没有完全掌握.最近场通过写装饰器模式的singleton来复习装饰器概念. 1. module实现 #模块实现 from

CSS的三种定位方式介绍(转载)

在CSS中一共有N种定位方式,其中,static ,relative,absolute三种方式是最基本最常用的三种定位方式.他们的基 本介绍如下. static默认定位方式relative相对定位,相对于原来的位置,但是原来的位置仍然保留absolute定位,相对于最近的非标准刘定位,原来的位置消失,被后边的位置所顶替 下面先演示相对定位的案例 [html] view plain copyprint? <!DOCTYPE html> <html> <head> <

MyEclipse中web服务器的三种配置方式

初学Javaweb开发的人们都会遇到一个问题,就是服务器环境的搭建配置问题.下面介绍三种服务器的搭建方式. 直接修改server.xml文件 当你写了一个web应用程序(jsp/servlet),想通过浏览器直接去访问这个页面,需要在Tomcat中配置相关路径: 找到Tomcat下conf目录,你会看到有个server.xml,即服务器配置文件.用文本编译器打开,拉到Host标签,在它结束前加上我们的应用程序路径: <Context path="/HelloWeb" docBas

1、打印二进制机器码,程序内存分析,大端序小端序,指针数组,数组指针,数组的三种访问方式,typedef,#if-0-#endif,求数组大小,括号表达式

 1.打印二进制机器码(分别表示32位的和64位的) #include <stdio.h> /*按照8位的长度打印一个数值*/ void dis8bit(char val) { int bit = 8; while(bit--) { if(1<<bit&val){ printf("1"); } else { printf("0"); } if(!(bit%4)) printf(" "); } putchar(1

SQL Server 中的三种分页方式

USE tempdb GO SET NOCOUNT ON --创建表结构 IF OBJECT_ID(N'ClassB', N'U') IS NOT NULL DROP TABLE ClassB GO CREATE TABLE ClassB(ID INT PRIMARY KEY, Name VARCHAR(16), CreateDate DATETIME, AID INT, Status INT) CREATE INDEX IDX_CreateDate ON ClassB(CreateDate)

支付宝5月4日起将停止收款主页业务 保留三种收款方式

4月28日消息,支付宝近日发布公告称,将于5月4日起停止收款主页业务(产品功能将无法使用),但并未公布停止业务的具体信息. 据了解,收款主页业务是用户可以自己制作一个支付宝账号的链接,把这个链接发给付款人后,对方就可以输入金额给该用户付款. 支付宝收款主页截图 支付宝公告称,收款主页业务停止之后,用户可以有三种方式进行收款:生成专属支付宝收款账户码,将账户二维码图片分享出去:在电脑上使用我要收款:在手机上,使用支付宝钱包的我要收款. 以下为公告原文: 鉴于收款主页(https://me.alip

Hibernate的Api以及三种查询方式

Hibernate  Api |-- Configuration       配置管理类对象 config.configure();    加载主配置文件的方法(hibernate.cfg.xml) 默认加载src/hibernate.cfg.xml config.configure("cn/config/hibernate.cfg.xml");   加载指定路径下指定名称的主配置文件 config.buildSessionFactory();   创建session的工厂对象 |--