day26 面向对象 单例模式总结
本文示例转载于知乎原文:
https://zhuanlan.zhihu.com/p/87524388
如果是在python2中,就需要手动继承object,
基于__new__方法
class Singleton: def __new__(cls, *args, **kwargs): if not hasattr(cls, "_isinstance"): cls._isinstance = super().__new__(cls) return cls._isinstance def __init__(self, x): self.x = x singleton = Singleton(89) print(id(singleton)) print("before-singleton>>>", singleton.x) single_2 = Singleton(78) print(id(single_2)) print(single_2.x) print("after-singleton>>>", singleton.x)
基于装饰器方法
def foo(cls, *args, **kwargs): dic = {} def _foo(): if cls not in dic: dic[cls] = cls(*args, **kwargs) return dic[cls] return _foo @foo class MyClass(object): def __init__(self): pass my = MyClass() my1 = MyClass() print(id(my) == id(my1))
基于元类metaclass实现,not yet
在python3里面,super就不需要再加参数了,直接写成"super()"就行。
知识点总结,封装,静态变量变成私有变量
单例模式,生产场景使用:数据库连接类,封装连接数据库的基础参数
class SqlClient(object): def __init__(self, host, user, passwd): self.host = host self.user = user self.passwd = passwd self.register() def register(self): self.info = "{}--{}---{}".format(self.host, self.user, self.passwd) def select(self): print("SELECT * FROM {}".format(self.host))
调用上面数据库连接类,做sql查询,如下是一种使用方法:
host = "10.293.291.19" user = "admin" passwd = "666666" def use_data_1(sql_client): sql_client.select() def use_data_2(sql_client): sql_client.select() def use_data_3(sql_client): sql_client.select() sql_client = SqlClient(host, user, passwd) use_data_1(sql_client) use_data_2(sql_client) use_data_3(sql_client)
开发中我们应该意识到一个问题,尽量少传参数,尤其是链式调用的函数,只在其中某几个环境用到,我们却需要不断的把它当作参数一致往下传递,如果这样的话,我们会发现,我们会传递很多参数,比如下面的例子:
host = "10.293.291.19" user = "admin" passwd = "666666" def use_data_1(sql_client): sql_client.select() use_data_2(sql_client) def use_data_2(sql_client): use_data_3(sql_client) def use_data_3(sql_client): sql_client.select() sql_client = SqlClient(host, user, passwd) use_data_1(sql_client)
下面用单例模式:
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 SqlClient(Singleton): """构建单例模式,避免重复传参数""" info = None def register(self, host, user, passwd): self.info = "{}--{}--{}".format(host, user, passwd) def select(self): print(self.info) # 使用单例模式 def use_data_1(): SqlClient().select() def use_data_2(): SqlClient().select() def use_data_3(): SqlClient().select() SqlClient().register(host, user, passwd) use_data_1() use_data_2() use_data_3()
依此可以发散思维一下,凡是类似的场景都可以考虑一下是否可以使用单例模式。
当然,凡事既有优点就会有缺点,单例模式也是,它可以实现系统的整体性和统一性,但是也不是在任何场景下都是适用的,例如,
- 多线程
- 可变对象
在这些场景下,它违背了单例模式单一性原则,而且很容易引起数据错误。
因此,使用单例模式之前需要考虑一下对应场景是否适合,如果适合,单例模式能够大大提高代码的效率,同时使得代码更加简洁,但是如果不适合而强行使用单例模式,那样会导致很多未知的问题。
本文示例转载于知乎原文:
https://zhuanlan.zhihu.com/p/87524388