• 设计模式----单利模式


    设计模式介绍

      设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码。反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。设计模式不会绑定具体的编程语言。一个好的设计模式应该能够用大部分编程语言实现(如果做不到全部的话,具体取决于语言特性)。最为重要的是,设计模式也是一把双刃剑,如果设计模式被用在不恰当的情形下将会造成灾难,进而带来无穷的麻烦。然而如果设计模式在正确的时间被用在正确地地方,它将是你的救星。

      起初,你会认为“模式”就是为了解决一类特定问题而特别想出来的明智之举。说的没错,看起来的确是通过很多人一起工作,从不同的角度看待问题进而形成的一个最通用、最灵活的解决方案。也许这些问题你曾经见过或是曾经解决过,但是你的解决方案很可能没有模式这么完备。

    单例模式存在意义

    模式特点:

    保证类仅有一个实例,避免内存浪费,并提供一个访问它的全局访问点。

    1. 设计模式在所有语言内都是通用的
    2. 设计模式存在的意义就是让代码设计结构设计的更好

    (程序如果并发量大的话,内存里就会存在非常多功能上一模一样的对象。存在这些对象肯定会消耗内存,对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用)

    # 单例模式
     
    class Foo:
     
        __n = None
     
        def __init__(self):
            self.name = "mosson"
            self.age = 18
            self.job = "pythoner"
     
        @staticmethod
        def dl():
            if Foo.__n:
                return Foo.__n
            else:
                Foo.__n = Foo()
                return Foo.__n
     
     
    # 创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.dl() 。
     
    f1 = Foo.dl()
    print(f1)
    f2 =Foo.dl()
    print(f2)
    f3 =Foo.dl()
    print(f3)
     
    # 运行结果
    <__main__.Foo object at 0x0000000001142390>
    <__main__.Foo object at 0x0000000001142390>
    <__main__.Foo object at 0x0000000001142390>
    

    ----------------------------------------------------------------------------------------------------

    demo-1: 创建三个游戏人物分别是:

    • 苍井井,女,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)      # 创建波多多角色
    创建实例

    demo-2:创建对数据库操作的公共类

    # #### 定义类 ####
    
    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()
    创建实例

    装饰器方式单例模式

    # 装饰器方式单例模式
     
    def singleton(argv):
        dic = {}
     
        def s(*args, **kwargs):
     
            if argv not in dic:
                dic[argv] = argv(*args, **kwargs)
                return dic[argv]
            else:
                return dic[argv]
     
        return s
     
     
    # 类上加单例装饰器
    @singleton
    class Foo:
        pass
     
    @singleton
    class Foo2:
        pass
    

     实例:结合场景二实现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() 。

    这样多个人链接服务器访问地址就会只在内存中拿一份了

    #!/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(single)
            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()
    Web应用实例-单例模式
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from wsgiref.simple_server import make_server
    
    class ConnectionPool:
    
        __instance = None
    
        def __init__(self):
            self.ip = "1.1.1.1"
            self.port = 3306
            self.pwd = "123123"
            self.username = 'xxxx'
            # 去连接
            self.conn_list = [1,2,3,4,5,6,7,8,9, 10]
    
        @staticmethod
        def get_instance():
            if ConnectionPool.__instance:
                return ConnectionPool.__instance
            else:
                # 创建一个对象,并将对象赋值给静态字段 __instance
                ConnectionPool.__instance = ConnectionPool()
                return ConnectionPool.__instance
    
        def get_connection(self):
            # 获取连接
            import random
            r = random.randrange(1,11)
            return r
    
    def index():
        # p = ConnectionPool()
        # print(p)
        p = ConnectionPool.get_instance()
        conn = p.get_connection()
        return "fuck u bitch   " + str(conn)
    
    def news():
        return 'bitchbitchbitchbitch'
    
    def RunServer(environ, start_response):
        start_response(status='200 OK', headers=[('Content-Type', 'text/html')])
    
        url = environ['PATH_INFO']
        if url.endswith('index'):
            ret = index()
            return ret
        elif url.endswith('news'):
            ret = news()
            return ret
        else:
            return "404"
    
    
    if __name__ == '__main__':
        httpd = make_server('', 8077, RunServer)
        print("Serving HTTP on port 8008...")
        httpd.serve_forever()
    Web应用实例-单例模式

    总结:单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费!!!


     多种样式的单利

    1 使用__new__方法

    class Singleton(object):
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                orig = super(Singleton, cls)
                cls._instance = orig.__new__(cls, *args, **kw)
            return cls._instance
     
    class MyClass(Singleton):
        a = 1
    

    2 共享属性

    创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法.

    class Borg(object):
        _state = {}
        def __new__(cls, *args, **kw):
            ob = super(Borg, cls).__new__(cls, *args, **kw)
            ob.__dict__ = cls._state
            return ob
     
    class MyClass2(Borg):
        a = 1
    

    3 装饰器版本

    def singleton(cls, *args, **kw):
        instances = {}
        def getinstance():
            if cls not in instances:
                instances[cls] = cls(*args, **kw)
            return instances[cls]
        return getinstance
     
    @singleton
    class MyClass:
      ...
  • 相关阅读:
    Mysql 分页查询sql优化
    观察者模式之spring事件机制
    封装一个按Key排序的Map工具
    SpringBoot java配置类@Configuration 的两种写法
    最基础前端路由实现,事件popstate使用
    mybatis分页插件PageHelper源码浅析
    看看线程特有对象ThreadLocal
    svn提交错误:Commit failed (details follow): Can't create directory
    mac下修复exfat格式外置硬盘
    [twisted] Multiple users
  • 原文地址:https://www.cnblogs.com/mosson/p/5685667.html
Copyright © 2020-2023  润新知