设计模式之单例模式

单例,顾名思义就是单个实例

 

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()

  

 

原文地址:https://www.cnblogs.com/chenchao1990/p/5376956.html