Python学习:Python设计模式-单例模式

1、单例模式存在的意义

  在这里的单例就是只有一个实例(这里的实例就像在面向对象的时候,建立了一个对象也能够说建立了一个实例),只用一个实例进行程序设计,首先咱们能够了解一下何时不适合使用单例模式,好比咱们须要使用类同时建立多个对象的时候,且每一个对象中封装了不一样的数据的时候,就不能使用单例模式,就像下面的例子python

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


zhangsan = Person('张三', 21)
lisi = Person('李四', 38)
wangwu = Person('王五', 37)  

  那么何时适合使用单例模式,若是每一个对象中封装了相同的数据,可是须要建立多个对象的时候,并且这两个实例全部的功能是同样的,因此咱们就可使用一个实例完成,在这里咱们就可使用单例模式,以下数据库

class Person:
    def __init__(self):
        self.name = '123'
        self.age = '20'

    def f1(self):
        pass

    def f2(self):
        pass


zhangsan = Person()
zhangsan.f1()

lisi = Person()
lisi.f1()

  为何要使用单例模式,就是为了在封装数据相同的状况下,并且每一个实例可执行的方法相同的时候,没必要建立多个对象,只须要使用一个实例,来完成多个相同实例所完成的功能,经过这种方式减小内存的使用。多线程

2、单例模式应用的场景  

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

3、单例模式的优势以及缺点

优势dom

系统内存中该类只存在一个对象,节省了系统资源,对于一些须要频繁建立销毁的对象,使用单例模式能够提升系统性能。工具

因为单例模式在内存中只有一个实例,减小了内存开销。性能

单例模式能够避免对资源的多重占用,例如一个写文件时,因为只有一个实例存在内存中,避免对同一个资源文件的同时写操做。优化

单例模式能够在系统设置全局的访问点,优化和共享资源访问。spa

其中使用到单例模式时,考虑较多的就是多线程的状况下如何防止被多线程同时建立等问题。线程

当这个类的对象在多个地方建立的时候,使得内部的方法屡次调用,可是但愿只要一个对象操做这个方法,或者不但愿多个地方同时调用这个方法,须要保持这个方法的单一性质,就用单例模式。设计

缺点

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

4、单例模式代码编写

接下来咱们就模拟一个数据库链接池来实现单例模式

首先咱们介绍一下数据库链接池

咱们经过程序进行数据库的操做的时候,每次都须要链接数据库,可是链接数据库须要消耗较多的时间,因此咱们能够在咱们主机的内存里维护一个数据库链接池,在这个链接池中有若干个已经链接数据库的链接,咱们想要链接数据库的时候直接到链接池中取出一个链接便可,省去了链接的时间。

非单例模式

import random


class SqlConnectionPool:
    __instance = None

    def __init__(self):
        self.ip = '127.0.0.1'
        self.port = 3306
        self.pwd = '123456'
        self.username = 'jhong'
        # 去链接
        self.conn_list = [1, 2, 3, 4, 5, 6, 7, 8]

    def get_connection(self):
        # 获取链接
        r = random.randrange(1, 9)
        return r


# 咱们建立多个对象内存地址是同样的,说明拿到的是同一个对象
obj = SqlConnectionPool()
print(obj)
obj1 = SqlConnectionPool()
print(obj1)
obj2 = SqlConnectionPool()
print(obj2)  

输出结果:

能够发现非单例模式每次内存输出的结果都不一样,下面是单例模式:

import random


class SqlConnectionPool:
    __instance = None

    def __init__(self):
        self.ip = '127.0.0.1'
        self.port = 3306
        self.pwd = '123456'
        self.username = 'jhong'
        # 去链接
        self.conn_list = [1, 2, 3, 4, 5, 6, 7, 8]

    @staticmethod  # 静态方法是由类调用的
    def get_instance():
        if SqlConnectionPool.__instance:
            return SqlConnectionPool.__instance
        else:
            # 建立一个对象,并将对象赋值给静态字段__instance
            SqlConnectionPool.__instance = SqlConnectionPool()
            return SqlConnectionPool.__instance

    # 单例模式关键代码解析
    # 当第一次调用这个静态方法的时候,判断__instance的值是None因此执行else,而后在else中建立一个对象赋值给静态字段__instance,而后返回这个静态字段
    # 第二次调用这个静态方法的时候,判断__instance的值为真,因此直接返回这个静态字段,而这个静态字段中包含的是第一次建立的对象,因此在之后调用这个方法就只会调用第一次建立的对象,这就是单例模式
    def get_connection(self):
        # 获取链接
        r = random.randrange(1, 9)
        return r


# 咱们建立多个对象内存地址是同样的,说明拿到的是同一个对象
obj = SqlConnectionPool.get_instance()
print(obj)
obj1 = SqlConnectionPool.get_instance()
print(obj1)
obj2 = SqlConnectionPool.get_instance()
print(obj2)  

输出结果:

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

相关文章
相关标签/搜索