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

设计模式介绍

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

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

单例模式存在意义

模式特点:

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

  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:
  ...
posted @ 2016-09-14 18:29  想做土匪的书生  阅读(284)  评论(0编辑  收藏  举报