zoukankan      html  css  js  c++  java
  • Python设计模式之一(单例模式)

    单例模式就是告诉你,只有一个对象

    (1)单例模式不适用的场景

    #单例模式就是告诉你,其实只有一个对象
    class Person:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    '''
    假设这样一个场景,有一个专门创造人的这样一个类,在我们每实例化创造一个人的时候,
    我们要赋予这个人姓名,年龄,基本,身高,等等,这种模式明显不适用单例模式,因为有多个对象,
    且每个对象都封装了不同属性,单例模式则只能允许创建一个人,所以不适用
    '''
    xiaoming=Person('小明',18)
    xiaoyue =Person('小月',19)
    xiaohong = Person('小红',28)
    

    (2)当所有实例中封装的数据相同时,就可以使用单例模式,例如

    class Person2:
        def __init__(self):
            self.name = 'jay'
            self.age = 33
        def f1(self):
            pass
        def f2(self):
            pass
    
    xiaoming =Person2()
    xiaoming.f1()
    '''创建了两个相同的实例,浪费内存,这种情景可以使用单例模式了'''
    xiaoming = Person2()
    xiaoming.f1()
    

    还有一个经典的使用场景,机器之间数据库的链接

    下面对这种单例模式进行探讨,假设创建一个连接池

    import random
    class ConnectionPool:
        def __init__(self):#链接数据库需要的通行证
            self.ip= '2.2.2.2'
            self.port= 6379
            self.pwd = '654321'
            self.username = 'jay'
            #去链接
            self.conn_list = [1,2,3,4,5,6]#假设创建了6个链接
        def get_connection(self):
            #获取链接,这里具体每写,只是个例子
            r = random.randrange(1,6)
            return r
    
    pool=ConnectionPool()
    for i in range(6):   conn = pool.get_connection()#进行链接,每次链接的时候进去拿一个连接就好了,不用再实例化一个对象

     这样个人每次在操作的时候都是一个单例模式,用一个实例进行链接,但是如果多个人同事打开这个文件,还是会实例化多个同样的对象,浪费内存

    我们可以这样操作,使在内存里面每次调用的时候都似乎获取到第一次创建的实例

    import random
    class ConnectionPool:
        __instance = None#默认是None
        def __init__(self):#链接数据库需要的通行证
            self.ip= '2.2.2.2'
            self.port= 6379
            self.pwd = '654321'
            self.username = 'jay'
            #去链接
            self.conn_list = [1,2,3,4,5,6]#假设创建了6个链接
        @staticmethod
        def get_instance():
            if ConnectionPool.__instance:#如果实例已经存在,则直接返回创建过的实例
                return  ConnectionPool.__instance
            else:
                ConnectionPool.__instance =ConnectionPool()#如果是第一次调用,执行该函数,实例化一个连接池
                return ConnectionPool.__instance#将对象赋值给静态字段
        def get_connection(self):
            #获取链接
            r = random.randrange(1,6)
            return r
    
    
    obj1= ConnectionPool.get_instance()
    print(obj1)
    obj2= ConnectionPool.get_instance()
    print(obj2)
    obj3= ConnectionPool.get_instance()
    print(obj3)
    obj4= ConnectionPool.get_instance()
    print(obj4)
    

      结果如图

    (3)创建web站点的单例模式

    这里是用简单的Python代码写一个网站

    from wsgiref.simple_server import make_server
    
    
    def index():
        return 'index'
    def news():
        return 'nnnnnnn'
    def RunSever(environ,start_response):
        start_response(status='200 ok',headers=[('Content-Type','text/html')])
        url=environ['PATH_INFO']#这是用户访问的url
        #这里我们访问http://127.0.0.1:8000/
    
        if url.endswith('index'):#根据网页以什么什么结尾则决定调用的函数
            return index()
    
        elif url.endswith('news'):
            return news()
        else:
            return '404'
    '''
    这里表示的是当我们访问http://127.0.0.1:8000/index,则返回index函数的执行结果,其他同理
    这里相当于搞了个网站
    '''
    
    if __name__ == '__main__':
    
        httpd= make_server('',8000,RunSever)#相当于启动一个网站,8000在这里表示端口
        print('Server HTTP on port 8008...')
        httpd.serve_forever()#一直监听该端口,内部有个while循环,等待别人访问
    

      当我们执行的时候,浏览器打开这个这个网站,则会根据条件返回相关数据,结果如图

         

    只要有人来请求了,则会在内存里面执行一次RunSever函数,给请求人结果,

    当我们把上面那个ConnectionPool类的代码加进这个web站点里面,可以使用单例模式,使访问的用户每次只调用同一个实例

    from wsgiref.simple_server import make_server
    import random
    
    
    
    
    class ConnectionPool:
        __instance = None#默认是None
        def __init__(self):#链接数据库需要的通行证
            self.ip= '2.2.2.2'
            self.port= 6379
            self.pwd = '654321'
            self.username = 'jay'
            #去链接
            self.conn_list = [1,2,3,4,5,6]#假设创建了6个链接
        @staticmethod
        def get_instance():
            if ConnectionPool.__instance:#如果实例已经存在,则直接返回创建过的实例
                return  ConnectionPool.__instance
            else:
                ConnectionPool.__instance =ConnectionPool()#如果是第一次调用,执行该函数,实例化一个连接池
                return ConnectionPool.__instance#将对象赋值给静态字段
        def get_connection(self):
            #获取链接
            r = random.randrange(1,6)
            return r
    
    def index():
        p = ConnectionPool.get_instance()
        print(p)  # 这里使每次用户访问的时候都调用同一个类,节约内存,之后则可以调用ConnectionPool的方法,例如选取链接
        return 'index'
    def news():
        return 'nnnnnnn'
    def RunSever(environ,start_response):
        start_response(status='200 ok',headers=[('Content-Type','text/html')])
        url=environ['PATH_INFO']#这是用户访问的url
        #这里我们访问http://127.0.0.1:8000
    
        if url.endswith('index'):#根据网页以什么什么结尾则决定调用的函数
            return index()
    
        elif url.endswith('news'):
            return news()
        else:
            return '404'
    '''
    这里表示的是当我们访问http://127.0.0.1:8000/index,则返回index函数的执行结果,其他同理
    这里相当于搞了个网站
    '''
    
    if __name__ == '__main__':
    
        httpd= make_server('',8000,RunSever)#相当于启动一个网站,8000在这里表示端口
        print('Server HTTP on port 8008...')
        httpd.serve_forever()#一直监听该端口,内部有个while循环,等待别人访问
    

      这样,每次就算不同的人访问该页面,都是调用同一个类的方法,可以节约服务器内存

    结果如图,都是同一个内存

  • 相关阅读:
    (转)Dynamic Web project转成Maven项目
    (转)nodejs搭建本地http服务器
    jquery mobile validation
    Quartz任务调度快速入门(转)
    珠宝首饰
    免费素材:25套免费的 Web UI 设计的界面元素(转)
    WebUI框架
    超越大典汽车维修系统
    如何申请开通微信多客服功能
    微信开发者文档连接
  • 原文地址:https://www.cnblogs.com/xiaobeibei26/p/6440507.html
Copyright © 2011-2022 走看看