目录
参考:《Python设计模式》作者:印度Chetan Giridhar,翻译:韩波
1. 面向对象的设计原则
- 开放/封闭原则:功能扩展开放,修改封闭。
- 控制反转原则:高层级的模块不应该依赖于底层及的模块,它们应该都依赖于抽象。
- 接口隔离原则:客户端不应该依赖于它们不需要使用的接口。
- 单一职责原则:类的职责单一,引起类变化的原因单一。
- 替换原则:扩展基类,派生类必须能够完全取代基类。
2. 设计模式(是一种思想)
1. 模式分类
创建型模式(例如单例模式)
- 运行机制基于对象的创建方式
- 它们将对象创建的细节隔离开来
- 代码与所创建的对象的类型无关
结构型模式(例如适配器模式)
- 它们致力于设计出能够通过组合获得更强大功能的对象和类的结构
- 重点是简化结构并识别类和对象之间的关系
- 它们主要关注类的继承和组合
行为型模式(例如观察者模式)
- 它们关注对象之间的就i傲虎以及对象的响应性
- 对象应该能够交互,同时仍然保持松散耦合
3. 单例模式
3.1 单例模式定义及简单实现
单例模式指程序运行过程中只能生成一个实例,以避免对同一资源产生相互冲突的请求。例如数据库操作,日志服务合并多台服务器产生的日志。
- 经典单例模式
- 只允许生成一个实例
- 如果已经有一个实例了,会重复提供同一个对象。
- 懒汉实例化
懒汉实例化确保在实际需要时才创建对象。
3.2 元类
1.__new__(cls, *args, **kwargs) 创建对象时调用,返回当前对象的一个实例;注意:这里的第一个参数是cls即class本身
2.__init__(self, *args, **kwargs) 创建完对象后调用,对当前对象的实例的一些初始化,无返回值,即在调用__new__之后,根据返回的实例初始化;注意,这里的第一个参数是self即对象本身【注意和new的区别】
3.__call__(self, *args, **kwargs) 如果类实现了这个方法,相当于把这个类型的对象当作函数来使用,相当于重载了括号运算符
class A():
def __call__(self, name):
print("name: %s" % name)
a = A()
a("John")
-----Output-----
name: John
type是所有类型的元类, 不论是python内置的int类型,还是自定义的class,当加载模块时,由type创建类类型的类。
类型的类是type,即type(Hello) = <class 'type'>
参考:廖雪峰-元类
3.3 用元类实现单例模式
class MyInt(type):
def __call__(cls, *args, **kwds):
print("******* Here is MyInt ********", args)
print("Now do whatever you want with these objects...")
return type.__call__(cls, *args, **kwds)
class int():
__metaclass__ = MyInt
def __init__(self, x, y):
self.x = x
self.y = y
i = int(4, 5)
--------output-----
('******* Here is MyInt ********', (4, 5))
Now do whatever you want with these objects...
对于已经存在的类来说,当需要创建对象时,将调用Python的特殊方法__call__。在这段代码中,当我们使用int(4,5)实例化int类时,MyInt元类的__call__方法将被调用,这意味着现在元类控制着对象的实例化。
class MetaSingleton(type):
_instances1 = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances1:
cls._instances1[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
print(cls)
return cls._instances1[cls]
class Logger():
__metaclass__=MetaSingleton
pass
logger1 = Logger()
logger2 = Logger()
print(logger1, logger2)
------- Output -------------
<class '__main__.Logger'>
(<__main__.Logger object at 0x035E9150>, <__main__.Logger object at 0x035E9150>)
综上,单例模式在运行期间只有一个实例,这个实例由全局类变量保存,可以使用元类方式实现单例模式,即由元类控制类的实例化(类的实例化由父类实现)。