思想:不改变原来代码情况下,扩展功能
意图:
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。
适用性:
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
处理那些可以撤消的职责。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
案例一
'''
Decorator
'''
class foo(object):
def f1(self):
print("original f1")
def f2(self):
print("original f2")
class foo_decorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print("decorated f1")
self._decoratee.f1()
def __getattr__(self, name):
return getattr(self._decoratee, name)
u = foo()
v = foo_decorator(u)
v.f1()
v.f2()
案例二:以关系型数据库和非关系数据执行操作语句为例,需求在不改变源代码的情况下,使用装饰器新增打印日志的功能
class NosqlDB:
def open(self, id, port):
print("打开了ip为:%s,端口为:%s的数据库" % (id, port))
def save(self, sql):
print("执行了Json命令:%s" % sql)
def close(self):
print("关闭")
class SqlDB:
def open(self, id, port):
print("打开了ip为:%s,端口为:%s的数据库" % (id, port))
def save(self, sql):
print("执行了sql命令:%s" % sql)
def close(self):
print("关闭")
class Decoratory:
def __init__(self,decoratee):
# decoratee为被装饰对象
self._decoratee=decoratee
def save(self,sql):
# 对比于之前,多了打印日志的步骤,打印后依然正常调用save方法
print("Log:%s"%sql)
self._decoratee.save(sql)
def __getattr__(self, item):
# 当调用该类中不存在的方法时,就调用被装饰对象的方法
return getattr(self._decoratee,item)
# 1.直接创建非关系型数据库对象,并调用方法
db=NosqlDB()
db.open('127.0.0.1',3306)
db.save("insert into......")
db.close()
# 2.创建一个装饰器对象,将非关系型数据库对象作为被装饰对象传入
db2=Decoratory(NosqlDB())
db2.open('127.0.0.1',3306)
db2.save("insert into......")
db2.close()
'''
第一种情况运行结果:(无打印日志)
打开了ip为:127.0.0.1,端口为:3306的数据库
执行了Json命令:insert into......
关闭
第二种情况运行结果:(包含打印日志)
打开了ip为:127.0.0.1,端口为:3306的数据库
Log:insert into......
执行了Json命令:insert into......
关闭
'''