复习下以前学过的设计模式,有时间就多写写,以python为主的,挨个内容进行实现
设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
另外两类,并发型模式和线程池模式。
从最简单的开始
单例模式:
单例模式很简单,就是保证全局唯一性的一个实例,这样对于一些建单的内容非常好用,比如我们在做一个数据库的访问的时候,因为操作的是一个数据库,所以我们想全局都用这一个实例来操作数据库。
涉及到的问题,就包括,如何保证实例唯一,如何在多线程环境下保证资源正确调度。
我们先给一些简单的实现:
1、基于模块的单例方式
模块天然的就是一个单例,所以直接利用模块是一个最方便的方法,比如
而且根据python的模块加载机制,加载pyc,这个单例是线程安全的,可以写代码试一下,其他情况暂时不明。
class Myobject(object):
def __init__(self):
time.sleep(1)
instance = Myobject()
2、基于装饰器的单例方式
def Singleton(cls):
_instances = {}
def wrapper(*args, **kwargs):
if cls not in _instances:
_instances[cls] = cls(*args, **kwargs)
return _instances[cls]
return wrapper
@Singleton
class MyObject(object):
def __init__(self):
time.sleep(1)
这种方式在多线程下是不安全的,因此我们加个锁
def Singleton(cls):
_instances = {}
mutex = threading.Lock()
def wrapper(*args, **kwargs):
with mutex:
if cls not in _instances:
_instances[cls] = cls(*args, **kwargs)
return _instances[cls]
return wrapper
3、使用类的方式
同样,该方式是有线程安全问题的,因此直接加上锁吧
class SingletonClass(object):
mutex = threading.Lock()
def __init__(self):
time.sleep(1)
pass
@classmethod
def instance(cls, *args, **kwargs):
with SingletonClass.mutex:
if not hasattr(SingletonClass, "_instance"):
SingletonClass._instance = SingletonClass(*args, **kwargs)
return SingletonClass._instance
4、基于__new__方法的单例
这个和上面的方式类似,一个类创建一个对象时,调用关系是 __new__,我们没写时,默认调用object.__new__,然后再调用__init__,所以可以尝试利用这个特性。
关于new和init的区别,面试问的估计也挺多,这里也整理下备份:
new其实才是构造函数,init是初始化函数,new将对象生成,然后init来初始化参数。
另外new可以用metaclass里面做一些事情
class SingletonNewClass(object):
mutex = threading.Lock()
def __init__(self):
pass
@classmethod
def __new__(cls, *args, **kwargs):
with SingletonNewClass.mutex:
if not hasattr(SingletonNewClass, "_instance"):
SingletonNewClass._instance = object.__new__(cls, *args, **kwargs)
return SingletonNewClass._instance
5、基于metaclass的单例模式
这个更进阶一些
metaclass的内容还是蛮多的,这里就不多说了,metaclass的关键是type,有一篇文章讲的特别好,将类,对象,元类的关系讲解的很清楚。
https://www.cnblogs.com/JetpropelledSnake/p/9094103.html
metaclass的单例基础是用type的方式生成类,类也是一种对象。
todo