1. 程式人生 > >python之路_flask框架_單例模式及session原理

python之路_flask框架_單例模式及session原理

sql content pytho his pri 我們 main imp dbutil

實例化補充:

技術分享圖片

一、單例模式

1、單例模式介紹

  單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。常見有如下四種單例模式:

單例模式1:模塊

  模塊是天然的單例模式,因為在模塊的第一次調用後會編譯成.pyc文件,在以後的調用過程中會會直接加載.pyc文件。

單例模式2:類@classmethod

(1)無法支持多線程情況:

class Singleton(object):

    def __init__(self):
        #模擬io阻塞
import time time.sleep(1) @classmethod def instance(cls,*args,**kwargs): if not hasattr(Singleton,"_instance"): Singleton._instance=Singleton(*args,**kwargs) return Singleton._instance #應用 obj1=Singleton.instance() obj2=Singleton.instance() print(obj1,obj2) #
<__main__.Singleton object at 0x000002C49DB6C5F8> <__main__.Singleton object at 0x000002C49DB6C5F8>

(2)支持多線程情況

import threading
class Singleton(object):
    _instance_lock=threading.Lock()
    def __init__(self):
        import time
        time.sleep(1)

    @classmethod
    def instance(cls,*args,**kwargs):
        
if not hasattr(Singleton,"_instance"): with Singleton._instance_lock: if not hasattr(Singleton,"_instance"): Singleton._instance=Singleton(*args,**kwargs) return Singleton._instance #應用 def task(n): obj=Singleton.instance() print(n,obj) for i in range(10): t=threading.Thread(target=task,args=[i,]) t.start()

單例模式3:基於__new__

(1)不支持多線程情況

class Singleton(object):
    def __init__(self):
        pass
    def __new__(cls, *args, **kwargs):
        if not hasattr(Singleton,"_instance"):
            Singleton._instance=object.__new__(cls,*args,**kwargs)
        return Singleton._instance
    
#應用:類實例化時會首先去執行__new__方法
obj=Singleton()

(2)支持多線程情況

import threading
class Singleton(object):
    _instance_lock=threading.Lock()
    def __init__(self):
        import time
        time.sleep(1)
    def __new__(cls, *args, **kwargs):
        if not  hasattr(Singleton,"_instance"):
            with Singleton._instance_lock:
                if not hasattr(Singleton,"_instance"):
                    Singleton._instance=object.__new__(cls,*args,**kwargs)
        return Singleton._instance
        
#應用:類實例化時會首先去執行__new__方法
def task(n):
    obj=Singleton()
    print(n,obj)
for i in range(10):
    t=threading.Thread(target=task,args=[i,])
    t.start()

單例模式4:基於metaclass

  分析如下:

"""
1.對象是類創建,創建對象時候類的__init__方法自動執行,對象()執行類的 __call__ 方法
2.類是type創建,創建類時候type的__init__方法自動執行,類() 執行type的 __call__方法(類的__new__方法,類的__init__方法)

# 第0步: 執行type的 __init__ 方法【類是type的對象】
class Foo:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        pass

# 第1步: 執行type的 __call__ 方法
#        1.1  調用 Foo類(是type的對象)的 __new__方法,用於創建對象。
#        1.2  調用 Foo類(是type的對象)的 __init__方法,用於對對象初始化。
obj = Foo()
# 第2步:執行Food的__call__ 方法
obj()
"""

  單例模式實例:

import threading
class SingletonType(type):
    _instance_lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
        return cls._instance

class Foo(metaclass=SingletonType):
    def __init__(self,name):
        self.name = name
obj1
= Foo(name) obj2 = Foo(name) print(obj1,obj2)

2、單例模式應用

  這裏主要針對我們上一章節講的數據庫連接池,將其與單例模式進行結合,使得任何用戶或者視圖在調用數據庫的時候,不需要反復實例化數據庫連接池對象,主要介紹如下:

import pymysql
import threading
from DBUtils.PooledDB import PooledDB

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

    def __init__(self):
        self.pool = PooledDB(
            creator=pymysql,
            maxconnections=6, 
            mincached=2, 
            maxcached=5,  
            maxshared=3,
            blocking=True, 
            maxusage=None, 
            setsession=[], 
            ping=0,
            host=127.0.0.1,
            port=3306,
            user=root,
            password=123,
            database=pooldb,
            charset=utf8
        )

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

    def connect(self):
        return self.pool.connection()

  上述數據庫連接池的單例模塊的引用的實例如下:

def run():
    pool = SingletonDBPool()               #實例化
    con = pool.connect()                   #創建連接
    # .........

    con.close()                            #關閉,不是真正的關閉

if __name__ == __main__:
    run()

二、自定義session

  參考文檔:https://python-team.gitbooks.io/flask-doc/content/di-si-zhang-kuo-zhan/11-nei-zhisession-yuan-li.html

python之路_flask框架_單例模式及session原理