Python:設計模式之單例模式
單例模式:
1、確保類有且只有一個對象被創建
2、為對象提供一個全局訪問點
3、控制共享資源的并行訪問
實現單例最簡單的方式:
使構造函數私有化,并創建一個靜態方法來完成對象初始化
使用場景:
一個類要求只有一個實例對象
單例模式的缺點
1、全局變量可能被誤修改
2、對同一個對象創建多個引用
3、所有依賴于全局變量的類都會由于一個類的改變而緊密耦合為全局數據,從而可能在無意中影響另一個類
一、經典的單例模式
只允許Singleton類生成一個實例
# -*- coding: utf-8 -*- class Singleton(object): def __new__(cls): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance if __name__ == '__main__': s1 = Singleton() s2 = Singleton() print(s1) print(s2) print(s1 == s2) print(s1 is s2) """ <__main__.Singleton object at 0x1021d58d0> <__main__.Singleton object at 0x1021d58d0> True True """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
二、懶漢式實例化
實際對象創建發生在 get_instance()
# -*- coding: utf-8 -*- class Singleton(object): __instance = None def __init__(self): if not Singleton.__instance: print("create...") else: print("already exist...") @classmethod def get_instance(cls): if not cls.__instance: cls.__instance = Singleton() return cls.__instance if __name__ == '__main__': s1 = Singleton.get_instance() # 實例化 s2 = Singleton.get_instance() # 已存在,不會實例化 print(s1) print(s2) print(s1 == s2) print(s1 is s2) """ create... <__main__.Singleton object at 0x101ad5860> <__main__.Singleton object at 0x101ad5860> True True """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
三、單態模式 Monostate
所有對象共享相同的狀態
# -*- coding: utf-8 -*- class Borg(object): __data = {"age": 23} def __init__(self): self.__dict__ = self.__data if __name__ == '__main__': b1 = Borg() b2 = Borg() # b1 和 b2是不同的對象,共享了相同的屬性 print(b1) print(b2) # 修改b1對象, b2對象的屬性也變化了 b1.name = "Tom" print(b1.__dict__) print(b2.__dict__) """ <__main__.Borg object at 0x102345f60> <__main__.Borg object at 0x1023452e8> {'age': 23, 'name': 'Tom'} {'age': 23, 'name': 'Tom'} """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
四、基于元類的單例
元類控制類的實例化
# -*- coding: utf-8 -*- class MetaSingleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class Logger(metaclass=MetaSingleton): pass if __name__ == '__main__': logger1 = Logger() logger2 = Logger() print(logger1) print(logger2) """ <__main__.Logger object at 0x1013658d0> <__main__.Logger object at 0x1013658d0> """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
五、單例模式應用一
對數據庫進行同步操作
# -*- coding: utf-8 -*- class MetaSingleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs) return cls._instances[cls] import sqlite3 class Database(metaclass=MetaSingleton): connection = None def __init__(self, db_url): self.db_url = db_url def get_cursor(self): if self.connection is None: self.connection = sqlite3.connect(self.db_url) self.cursor = self.connection.cursor() return self.cursor if __name__ == '__main__': db_url = "db.sqlite3" cursor1 = Database(db_url).get_cursor() cursor2 = Database(db_url).get_cursor() print(cursor1) print(cursor2) """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
六、單例模式應用二
監控服務器,共享服務器數據
# -*- coding: utf-8 -*- class HealthCheck(object): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(HealthCheck, cls).__new__(cls, *args, **kwargs) return cls._instance def __init__(self): self.servers = [] def add_server(self, server): self.servers.append(server) def pop_server(self): return self.servers.pop() def show_server(self): print("*" * 10) for server in self.servers: print(server) print("*" * 10) if __name__ == '__main__': h1 = HealthCheck() h2 = HealthCheck() h1.add_server("server1") h1.add_server("server2") h1.add_server("server3") h2.pop_server() h2.show_server() """ ********** server1 server2 ********** """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
總結
1、當要求一個類只有一個對象時,就可以使用單例模式
2、經典單例模式,允許多次實例化,但返回同一個對象
3、Borg或Monostate單態模式允許創建共享相同狀態的多個對象
4、單例模式可應用于多個服務間,實現一致的數據庫操作
參考:
《python設計模式第2版》第二章 單例設計模式
Python
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。