世界上只有两种程序员:「懂设计模式的」和「不懂设计模式的」。 懂设计模式的程序员,写出来的代码优雅如诗,易读易维护,扩展性也更强;不懂设计模式的程序员,代码随心所欲,但写完回头一看,往往自己都会一头雾水,可维护性几乎为零。 设计模式(Design Pattern)是几十年的开发人员经过长时间的试验和摸索,总结出来的一套 程序设计标准。它使得设计方案更加通俗易懂 —— 无论你使用哪种编程语言,做什么类型的项目,甚至处在一个国际化的开发团队,当面对同一个设计模式时,你和别人的理解就别无二致。 几乎所有的大型软件、编程语言、框架都使用了这些标准,也因此,设计模式变成了面试必考的问题,也是程序员的基本功之一。 学习和使用设计模式,可以: 1. 提高代码的可读性、可靠性、可复用性,使编程真正工程化; 2. 便于后期维护项目,增强系统的健壮性和扩展性; 3. 可以锻炼程序员的设计思维,提高代码质量。 下面,我们就来用 Python 学习 12 种最经典的设计模式,从单例模式讲起: 单例模式 设计模式是一套被反复使用且经过验证的比较高效的代码设计经验,对于我们经常会遇到的一些编程问题而言,它们是比较可靠的解决方案。 设计模式不分语言,大多数编程语言都可以实现。我们的课程针对 Python 实现最常见的几种设计模式进行讲解。 知识点
设计模式简介所谓“设计模式”就是一套由前人总结的代码的设计思路。以其中最常用的“单例模式”为例,在程序中我们有一个需求,这个需求的实现有多种思路,其中一种是创建一个类并且使得该类在多次实例化时生成唯一的一个实例。这就需要设计代码实现这个结果。大家发现这种场景下这样设计是最合理的,我们就管这种设计思路叫做“单例模式”。 设计模式不分语言,大多数编程语言都可以实现。 一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码。拿建造桥梁粗略地类比一下,一座桥是一个小功能,代码就是砖石瓦块钢筋水泥,设计模式就是我们要怎么建造,圆拱桥、独木桥、管道桥还是拉索桥。 设计模式很有用,但它要用到合适的场景中才能发挥应有的效果,否则可能出现弊大于利的情况。 通常来讲设计模式分为三类:
单例模式所谓单例模式,也就是说任何时候我们都要确保只有一个对象实例存在。很多情况下,整个系统中只需要存在一个对象,所有的信息都从这个对象获取,比如系统的配置对象,或者是线程池。这些场景下,就非常适合使用单例模式。总结起来,就是说不管我们实例化一个类多少次,真正干活的对象只会生成一次并且在首次实例化时生成。 在 Python 中实现单例模式的方式有很多,下面分别举例说明。 使用嵌套类实现在定义类 A 时,在类中再定义一个嵌套类 _A。首次对类 A 进行实例化时,将类 _A 的实例赋值给类 A 的属性 _instance ,然后给类 A 的实例定义一个 将如下代码写入 class Singleton: ''' 单例模式 ''' # 创建一个嵌套类 class _A: def display(self): # 1 return id(self) _instance = None def __init__(self): # 2 __class__._instance = __class__._instance or __class__._A() def __getattr__(self, attr): # 3 return getattr(__class__._instance, attr) def __setattr__(self, attr, value): # 4 object.__setattr__(__class__._instance, attr, value) if __name__ == '__main__': s1 = Singleton(); s2 = Singleton() # 5 print('id(s1):', id(s1)) # 6 print('id(s2):', id(s2)) print('s1.display():', s1.display()) # 7 print('s2.display():', s2.display()) s1.name = 'James' # 8 print('s1.name:', s1.name) print('s2.name:', s2.name) 如上所示,对代码进行简略说明:
终端执行脚本,操作结果如下所示: $ python3 singleton_1.py 如上所示,Singleton 的实例各不相同,它们在赋值属性和调用属性时,结果却是相同的。因为这些实例操作属性时都转移到了嵌套类 _A 的实例上。 使用装饰器实现以上代码虽然很好地实现了单例模式,但是在真正的项目开发中这种方式却不够灵活,因为我们要将真正干活的类内置在单例类中,这会有些麻烦,例如删除实例的属性这一点就不太好实现。 下面我们使用 Python 装饰器来实现单例模式。 首先创建一个「类装饰器」,也就是编写一个类,这个类作为装饰器。这个「类装饰器」在实例化的时候,将另一个类作为参数。类装饰器的名字是 SingletonDeco ,其 将如下代码写入 class SingletonDeco: ''' 单例类装饰器 ''' def __init__(self, cls): # 1 print('装饰器初始化') self._cls = cls def instance(self): # 2 try: return self._instance except AttributeError: self._instance = self._cls() return self._instance def __call__(self): # 3 return self.instance() @SingletonDeco # 4 class Singleton: def display(self): return id(self) if __name__ == '__main__': s1 = Singleton() # 5 s2 = Singleton() print('id(s1):', s1.display()) print('id(s2):', s2.display()) print('s1 is s2:', s1 is s2) 对代码进行简单描述:
终端执行结果如下: $ python3 singleton_2.py 以上代码中,我们用装饰器实现了单例模式,任何想使用单例模式的类,只需要使用 重写 __new__ 方法在对类进行实例化时,需要先调用类的 首先判断类属性 在对类进行实例化时,只有首次会创建类的实例,之后都是返回类的 将如下代码写入 class Singleton: def __new__(cls, *args, **kw): if not hasattr(cls, '_Singleton__instance'): cls.__instance = super().__new__(cls, *args, **kw) print('实例化时打印实例 ID:', id(cls.__instance)) return cls.__instance s1 = Singleton() s2 = Singleton() print('s1 is s2:', s1 is s2) 其中 如果不重写类的 终端执行程序结果如下: $ python3 singleton_3.py 总结本节实验主要介绍了设计模式的基本概念,并对创建型模式之一单例模式的实现进行了讲解,其中涉及到三个方法,它们可以根据实际场景进行恰当地选用。所有的设计都是为了实现对某个类的实例进行唯一的限制。 下一节实验我们将讲解一些额外的关于“元类”的知识,实际上它们用得很少,但这有助于我们理解一些特别的代码。 |
|