單列模式

單列模式

1、單列模式

1.1 什麼是單列模式

  1. 整個過程當中只是一個實例,全部生成的實例都指向同一塊內存地址
  2. 基於某種方法實例化屢次獲得的實例是同一個

理解:app

就像a= 1``b=1``c =1對a、b、c的地址進行打印,都是相同的code

1.2 爲啥用單列模式

當實例化屢次獲得的對象中存放的屬性都同樣的狀況,應該多個對象指向同一個內存,即同一個實例。對象

2、實現單列模式

模塊settings內存

#settings.py
PORT=3306
HOST='127.0.0.1'

方法1(經過類的綁定方法)

要求:get

  1. 當用戶輸入端口和地址,實例化產生新對象
  2. 當用戶不輸入端口和地址,每次拿到的對象,都是同一個
class Sql():
    _instance = None

    def __init__(self, port, host):
        self.port = port
        self.host = host

    @classmethod
    def get_sigoleton(cls):
        import settings
        if cls._instance:
            return cls._instance
        else:
            cls._instance = cls(settings.PORT, settings.HOST)
            return cls._instance


s1 = Sql.get_sigoleton()
s2 = Sql.get_sigoleton()
s3 = Sql.get_sigoleton()
print(s1)  # <__main__.Sql object at 0x000001D7F1BE1188>

print(s2)  # <__main__.Sql object at 0x000001D7F1BE1188>

print(s3)  # <__main__.Sql object at 0x000001D7F1BE1188>
s4 = Sql('33306', '192.168.1.1')
print(s4)  # <__main__.Sql object at 0x000001B2AD820348>

法2、經過裝飾器

要求:it

  1. 當用戶輸入端口和地址,實例化產生新對象
  2. 當用戶不輸入端口和地址,每次拿到的對象,都是同一個
def get_sigoleton(cls):
    # cls就是裝飾的時候把Sql傳入
    _instance = None

    def wrapper(*args, **kwargs):
        if len(args) != 0 or len(kwargs) != 0:
            # 表示傳入參數生成新對象
            res = cls(*args, **kwargs)
            return res
        else:
            import settings
            nonlocal _instance
            if not _instance:
                _instance = cls(settings.PORT, settings.HOST)
            return _instance

    return wrapper


@get_sigoleton
# 會把下面的Sql看成參數傳入,至關於:Sql = get_sigoleton(Sql)
class Sql():
    def __init__(self, port, host):
        self.port = port
        self.host = host


s1 = Sql()
s2 = Sql()
s3 = Sql()
print(s1)  # <__main__.Sql object at 0x000001E7AED841C8>

print(s2)  # <__main__.Sql object at 0x000001E7AED841C8>

print(s3)  # <__main__.Sql object at 0x000001E7AED841C8>

法3、經過元類

要求:class

  1. 當用戶輸入端口和地址,實例化產生新對象
  2. 當用戶不輸入端口和地址,每次拿到的對象,都是同一個
class Mymeta(type):
    def __init__(self, name, bases, dic):
        import settings
        # 把實例化好的對象,放到類的名稱空間內
        self._instance = self(settings.PORT, settings.HOST)
    def __call__(self, *args, **kwargs):
        # self是誰?是Sql類
        if len(args) != 0 or len(kwargs) != 0:
            obj = object.__new__(self)
            obj.__init__(*args, **kwargs)
            return obj
        else:
            return self._instance

class Sql(metaclass=Mymeta):
    # 至關於Sql = Mymeta(name,bases,dic)
    # 這個會調用Mymeta的__init__
    # 在裏面已經向類的名稱空間放了一個對象
    def __init__(self, port, host):
        self.port = port
        self.host = host
print(Sql.__dict__)
s1 = Sql()

法4、經過經過模塊導入(python的模塊是自然的單例)

要求:test

  1. 當用戶輸入端口和地址,實例化產生新對象
  2. 當用戶不輸入端口和地址,每次拿到的對象,都是同一個
#sigonleton.py
import settings
class Sql():
    def __init__(self,port,host):
        self.port = port
        self.host = host
s1 = Sql(settings.PORT,settings.HOST)
def test():
    from sigonleton import s1
    print(s1.port)
    print(s1)
def teat2():
    from sigonleton import s1 as s2
    print(s2)
test()
teat2()
相關文章
相關標籤/搜索