单例,顾名思义就是单个实例
1、单例模式的优点
- 单例模式只产生一个对象,减少了系统开销,当一个对象的产生需要的资源比较多时,如读取配置文件,产生其他依赖对象,则可以再其应用启动的时候直接产生一个单例对象。然后永久驻存在内存的方式来解决。
- 单例模式可以再系统设置全局访问点。优化共享资源的访问。例如可以设计一个单例类,负责所有数据表的映射。
2、单例实现方式
先来看一个普通场景:
这种普通的方法会在大的访问量下出现内存的消耗!
每个请求到来,都需要在内存里创建一个实例,再通过该实例执行指定的方法。
那么问题来了...如果并发量大的话,内存里就会存在非常多功能上一模一样的对象。
#!/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()
print id(db)
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()
上面的例子就是对数据库的操作。当操作量非常多时,会产生大量的内存消耗,因为每一个请求都创建了一份实例
对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用,也是极好的!!!
单例模式用来保证内存中仅存在一个实例!!!通过 类方法@classmethod 或静态方法 @staticmethod都可以实现
原理:通过面向对象的特性,构造出单例模式:
-
类方法 @classmethod (cls=当前类) 触发者是类,用类直接调用,括号里只能有一个参数cls对静态方法的约束,只能有一个参数,参数在传值的时候自动把当前类传入。单例模式时用到。
-
静态方法 属于类 @staticmethod 触发者类,括号里不需要参数()也可以有多个参数类加上静态方法=一个函数 。创建对象就可以访问方法,就像创建了函数。如果程序全部要求用面向对象做,而不用函数,静态方法才有用。
为什么要有类方法和静态方法?
因为如果没有这两种方法,在调用时就会先创建对象在去调用方法。而这两种方法都可以直接通过类来调用,节省的内存。
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server # ########### 单例类定义 ########### class DbHelper(object): __instance = None #创建一个私有静态字段,用来保存内存中永远存在的的实例字段 def __init__(self): self.hostname = '1.1.1.1' self.port = 3306 self.password = 'pwd' self.username = 'root' @staticmethod def singleton(): if DbHelper.__instance: return DbHelper.__instance else: DbHelper.__instance = DbHelper() return DbHelper.__instance def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 pass def create(self): # 连接数据库 # 拼接sql语句 # 操作 pass def remove(self): # 连接数据库 # 拼接sql语句 # 操作 pass def modify(self): # 连接数据库 # 拼接sql语句 # 操作 pass class Handler(object): def index(self): obj = DbHelper.singleton() #通过类直接调用静态方法 print id(obj) obj.create() 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()