zoukankan      html  css  js  c++  java
  • Python学习:19.Python设计模式-单例模式

    一、单例模式存在的意义

      在这里的单例就是只有一个实例(这里的实例就像在面向对象的时候,创建了一个对象也可以说创建了一个实例),只用一个实例进行程序设计,首先我们可以了解一下什么时候不适合使用单例模式,比如我们需要使用类同时创建多个对象的时候,且每个对象中封装了不同的数据的时候,就不能使用单例模式,就像下面的例子

    class Person:
        def __init__(self,name,age):
            self.name = name
            self.age = age
            
    mingming = Person('明明',19)
    mingyue = Person('明月',30)
    mingri = Person('明日',20)

      那么什么时候适合使用单例模式,如果每个对象中封装了相同的数据,但是需要创建多个对象的时候,而且这两个实例所有的功能是一样的,所以我们就可以使用一个实例完成,在这里我们就可以使用单例模式,如下

    class Person:
        def __init__(self):
            self.name = '123123'
            self.age = '20'
    
        def f1(self):
            pass
    
        def f2(self):
            pass
    
    mingming = Person()
    mingming.f1()
    
    mingyue = Person()
    mingyue.f1()

      为什么要使用单例模式,就是为了在封装数据相同的情况下,而且每个实例可执行的方法相同的时候,不必创建多个对象,只需要使用一个实例,来完成多个相同实例所完成的功能,通过这种方式减少内存的使用。

    二、单例模式应用的场景

    • 需要频繁的进行创建和销毁的对象;
    • 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
    • 工具类对象;
    • 频繁访问数据库或文件的对象。

    三、单例模式的优点以及缺点

    优点

    系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。

    由于单例模式在内存中只有一个实例,减少了内存开销。 
    单例模式可以避免对资源的多重占用,例如一个写文件时,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。 
    单例模式可以再系统设置全局的访问点,优化和共享资源访问。 
    其中使用到单例模式时,考虑较多的就是多线程的情况下如何防止被多线程同时创建等问题。

    当这个类的对象在多个地方创建的时候,使得内部的方法多次调用,但是希望只要一个对象操作这个方法,或者不希望多个地方同时调用这个方法,需要保持这个方法的单一性质,就用单利模式

    缺点

    使用单例模式,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。

    四、单例模式代码编写

    接下来我们就模拟一个数据库连接池来实现单例模式
    首先我们介绍一下数据库连接池
    我们通过程序进行数据库的操作的时候,每次都需要连接数据库,但是连接数据库需要消耗较多的时间,所以我们可以在我们主机的内存里维护一个数据库连接池,在这个连接池中有若干个已经连接数据库的连接,我们想要连接数据库的时候直接到连接池中取出一个连接即可,省去了连接的时间。

    非单例模式

    import random
    
    class SqlConnectionPool:
    
        __instance = None
    
        def __init__(self):
            self.ip = "127.0.0.1"
            self.port = 3306
            self.pwd = '123456'
            self.username = 'alexsel'
            #去连接
            self.conn_list = [1,2,3,4,5,6,7,8,9,10]
    
        def get_connection(self):
            #获取连接
            r = random.randrange(1,11)
            return r
    
    
    #我们创建多个对象内存地址是一样的,说明拿到的是同一个对象
    obj = SqlConnectionPool()
    print(obj)
    obj1 = SqlConnectionPool()
    print(obj1)
    obj2 = SqlConnectionPool()
    print(obj2)
    
    输出结果:
    <__main__.SqlConnectionPool instance at 0x0000000002630788>
    <__main__.SqlConnectionPool instance at 0x0000000002630888>
    <__main__.SqlConnectionPool instance at 0x00000000026308C8>

    非单例模式每次内存输出的结果都不同,下面是单例模式。

    import random
    
    class SqlConnectionPool:
    
        __instance = None
    
        def __init__(self):
            self.ip = "127.0.0.1"
            self.port = 3306
            self.pwd = '123456'
            self.username = 'alexsel'
            #去连接
            self.conn_list = [1,2,3,4,5,6,7,8,9,10]
    
        @staticmethod   #静态方法是由类调用的
        def get_instance():
            if SqlConnectionPool.__instance:
                return SqlConnectionPool.__instance
            else:
                #创建一个对象,并将对象赋值给静态字段__instance
                SqlConnectionPool.__instance = SqlConnectionPool()
                return SqlConnectionPool.__instance
    
        #单例模式关键代码解析
        #当第一次调用这个静态方法的时候,判断__instacne的值是None所以执行else,然后在else中创建一个对象赋给静态字段__instance,然后返回这个静态字段
        #第二次调用这个今静态方法的时候,判断__instance的值为真,所以直接返回这个静态字段,而这个静态字段中包含的是第一次创建的对象,所以在以后调用这个方法
        #就只会调用第一次创建的对象,这就是单例模式
    
        def get_connection(self):
            #获取连接
            r = random.randrange(1,11)
            return r
    
    
    #我们创建多个对象内存地址是一样的,说明拿到的是同一个对象
    obj = SqlConnectionPool.get_instance()
    print(obj)
    obj1 = SqlConnectionPool.get_instance()
    print(obj1)
    obj2 = SqlConnectionPool.get_instance()
    print(obj2)
    
    
    输出结果:
    <__main__.SqlConnectionPool instance at 0x000000000260C808>
    <__main__.SqlConnectionPool instance at 0x000000000260C808>
    <__main__.SqlConnectionPool instance at 0x000000000260C808>

     以上是基于类,使用静态字段和静态方法实现的一个单例模式。

  • 相关阅读:
    服务端渲染和客户端渲染
    node(基础)_node.js中的http服务以及模板引擎的渲染
    node基础(二)_模块以及处理乱码问题
    node(基础)_node中的javascript
    vue购物车和地址选配(三)
    nyoj 169 素数
    nyoj 205 求余数
    nyoj 65另一种阶乘问题
    nyoj 734奇数阶魔方
    nyoj64 鸡兔同笼
  • 原文地址:https://www.cnblogs.com/liudi2017/p/9393614.html
Copyright © 2011-2022 走看看