python基础-9.2 单例模式
设计模式
一、单例模式
单例,顾名思义单个实例。创建一个实例
链接池案例
1、单例=》只有一个实例
2、静态方法+静态字段
3、所有的实例中封装的内容相同时用单例模式
class ConnectionPoll: __instance = None #静态字段只有类可以访问 def __init__(self): self.ip = "1.1.1.1" self.port = 3306 self.pwd = 123 self.username = "root" self.conn_list = [1,2,3,4,5,6,7] @staticmethod def get_instance(): if ConnectionPoll.__instance: return ConnectionPoll.__instance else: #创建一个对象,并且赋值给__instance ConnectionPoll.__instance = ConnectionPoll() return ConnectionPoll.__instance #静态方法类去访问 obj1 = ConnectionPoll.get_instance() print(obj1) obj2 = ConnectionPoll.get_instance() print(obj2) obj2= ConnectionPoll.get_instance() print(obj2) --------------------------- <__main__.ConnectionPoll object at 0x000002FEC59D42E8> <__main__.ConnectionPoll object at 0x000002FEC59D42E8> <__main__.ConnectionPoll object at 0x000002FEC59D42E8>
学习单例之前,首先来回顾下面向对象的内容:
python的面向对象由两个非常重要的两个“东西”组成:类、实例
面向对象场景一:
如:创建三个游戏人物,分别是:
- 苍井井,女,18,初始战斗力1000
- 东尼木木,男,20,初始战斗力1800
- 波多多,女,19,初始战斗力2500
# ##################### 定义类 ##################### class Person: def __init__(self, na, gen, age, fig): self.name = na self.gender = gen self.age = age self.fight =fig def grassland(self): """注释:草丛战斗,消耗200战斗力""" self.fight = self.fight - 200 # ##################### 创建实例 ##################### cang = Person('苍井井', '女', 18, 1000) # 创建苍井井角色 dong = Person('东尼木木', '男', 20, 1800) # 创建东尼木木角色 bo = Person('波多多', '女', 19, 2500) # 创建波多多角色 创建实例
面向对象场景二:
如:创建对数据库操作的公共类
- 增
- 删
- 改
- 查
# #### 定义类 #### class DbHelper(object): def __init__(self): self.hostname = '1.1.1.1' self.port = 3306 self.password = 'pwd' self.username = 'root' def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 pass def create(self): # 连接数据库 # 拼接sql语句 # 操作 pass def remove(self): # 连接数据库 # 拼接sql语句 # 操作 pass def modify(self): # 连接数据库 # 拼接sql语句 # 操作 pass # #### 操作类 #### db = DbHelper() db.create() 创建示例
实例:结合场景二实现Web应用程序
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server class DbHelper(object): def __init__(self): self.hostname = '1.1.1.1' self.port = 3306 self.password = 'pwd' self.username = 'root' def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 return 'fetch' def create(self): # 连接数据库 # 拼接sql语句 # 操作 return 'create' def remove(self): # 连接数据库 # 拼接sql语句 # 操作 return 'remove' def modify(self): # 连接数据库 # 拼接sql语句 # 操作 return 'modify' class Handler(object): def index(self): # 创建对象 db = DbHelper() db.fetch() return 'index' def news(self): return 'news' def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] temp = url.split('/')[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return '404 not found' if __name__ == '__main__': httpd = make_server('', 8001, RunServer) print "Serving HTTP on port 8001..." httpd.serve_forever() Web应用程序实例 测试代码
对于上述实例,每个请求到来,都需要在内存里创建一个实例,再通过该实例执行指定的方法。
那么问题来了...如果并发量大的话,内存里就会存在非常多功能上一模一样的对象。存在这些对象肯定会消耗内存,对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用,也是极好的!!!
单例模式出马,单例模式用来保证内存中仅存在一个实例!!!
通过面向对象的特性,构造出单例模式:
#!/usr/bin/env python # _*_ coding:utf-8 _*_ class ConnectionPoll: __instance = None def __init__(self): self.ip = "1.1.1.1" self.port = 3306 self.pwd = 123 self.username = "root" self.conn_list = [1,2,3,4,5,6,7] @staticmethod def get_instance(): if ConnectionPoll.__instance: return ConnectionPoll.__instance else: ConnectionPoll.__instance = ConnectionPoll() return ConnectionPoll.__instance obj1 = ConnectionPoll.get_instance() print(obj1) obj2 = ConnectionPoll.get_instance() print(obj2) obj2= ConnectionPoll.get_instance() print(obj2) 通过面向对象的特性,构造出单例模式:
# ########### 单例类定义 ########### class Foo(object): __instance = None @staticmethod def singleton(): if Foo.__instance: return Foo.__instance else: Foo.__instance = Foo() return Foo.__instance # ########### 获取实例 ########### obj = Foo.singleton()
对于Python单例模式,创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.singleton() 。
这样多个人链接服务器访问地址就会只在内存中拿一份了
1 #!/usr/bin/env python 2 #coding:utf-8 3 from wsgiref.simple_server import make_server 4 5 # ########### 单例类定义 ########### 6 class DbHelper(object): 7 8 __instance = None 9 10 def __init__(self): 11 self.hostname = '1.1.1.1' 12 self.port = 3306 13 self.password = 'pwd' 14 self.username = 'root' 15 16 @staticmethod 17 def singleton(): 18 if DbHelper.__instance: 19 return DbHelper.__instance 20 else: 21 DbHelper.__instance = DbHelper() 22 return DbHelper.__instance 23 24 def fetch(self): 25 # 连接数据库 26 # 拼接sql语句 27 # 操作 28 pass 29 30 def create(self): 31 # 连接数据库 32 # 拼接sql语句 33 # 操作 34 pass 35 36 def remove(self): 37 # 连接数据库 38 # 拼接sql语句 39 # 操作 40 pass 41 42 def modify(self): 43 # 连接数据库 44 # 拼接sql语句 45 # 操作 46 pass 47 48 49 class Handler(object): 50 51 def index(self): 52 obj = DbHelper.singleton() 53 print id(single) 54 obj.create() 55 return 'index' 56 57 def news(self): 58 return 'news' 59 60 61 def RunServer(environ, start_response): 62 start_response('200 OK', [('Content-Type', 'text/html')]) 63 url = environ['PATH_INFO'] 64 temp = url.split('/')[1] 65 obj = Handler() 66 is_exist = hasattr(obj, temp) 67 if is_exist: 68 func = getattr(obj, temp) 69 ret = func() 70 return ret 71 else: 72 return '404 not found' 73 74 if __name__ == '__main__': 75 httpd = make_server('', 8001, RunServer) 76 print "Serving HTTP on port 8001..." 77 httpd.serve_forever() 78 79 Web应用实例-单例模式
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 from wsgiref.simple_server import make_server 4 5 class ConnectionPool: 6 7 __instance = None 8 9 def __init__(self): 10 self.ip = "1.1.1.1" 11 self.port = 3306 12 self.pwd = "123123" 13 self.username = 'xxxx' 14 # 去连接 15 self.conn_list = [1,2,3,4,5,6,7,8,9, 10] 16 17 @staticmethod 18 def get_instance(): 19 if ConnectionPool.__instance: 20 return ConnectionPool.__instance 21 else: 22 # 创建一个对象,并将对象赋值给静态字段 __instance 23 ConnectionPool.__instance = ConnectionPool() 24 return ConnectionPool.__instance 25 26 def get_connection(self): 27 # 获取连接 28 import random 29 r = random.randrange(1,11) 30 return r 31 32 def index(): 33 # p = ConnectionPool() 34 # print(p) 35 p = ConnectionPool.get_instance() 36 conn = p.get_connection() 37 return "fuck u bitch " + str(conn) 38 39 def news(): 40 return 'bitchbitchbitchbitch' 41 42 def RunServer(environ, start_response): 43 start_response(status='200 OK', headers=[('Content-Type', 'text/html')]) 44 45 url = environ['PATH_INFO'] 46 if url.endswith('index'): 47 ret = index() 48 return ret 49 elif url.endswith('news'): 50 ret = news() 51 return ret 52 else: 53 return "404" 54 55 56 if __name__ == '__main__': 57 httpd = make_server('', 8077, RunServer) 58 print("Serving HTTP on port 8008...") 59 httpd.serve_forever() 60 61 Web应用实例-单例模式
总结:单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费!!!