分析Python中设计模式之Decorator装饰器模式的要点
|
先给出一个四人团对Decorator mode的定义:动态地给一个对象添加一些额外的职责。 @aoo def foo(): pass def aoo(fn): return fn 装饰模式强调动态地给对象添加额外的功能。 Python内置了很多对装饰器的支持,因此在Python中使用装饰模式是非常容易的,下面是一个典型的例子,给函数增加日志功能: import functools def log_wrapper(fun): @functools.wraps(fun) def wrapper(*args,**kwargs): print '在函数执行前加日志' ret = fun(*args,**kwargs) print '在函数执行后家日志' return ret return wrapper @log_wrapper def test(): print 'Hello,世界' functools.wraps是Python标准库提供的一个特殊的装饰器,用来解决装饰器带来的一些常规问题,如函数名称、doc等的不一致问题。@是Python针对装饰器提供的一个语法糖,上面的@log_wrapper相当于wrap_test = log_rapper(test),用@后,这个步骤由解释器代劳了。 装饰器是Python编程必须掌握的一项技能,在编码过程中经常会用到。 这里只是一个普通的内嵌函数
def foo(x):
y = x
def foo1 ():
a = 1
return a
return foo1
而下面boo则是一个闭包
def aoo(a,b):
c = a
def boo (x):
x = b + 1
return x
return boo
boo的特殊性在于引用了外部变量b,当aoo返回后,只要返回值(boo)一直存在,则对b的引用就会一直存在。
class Foo(object):
def __init__(self,…):
self.lock = threading.Lock()
def interface1(self,…):
self.lock.acquire()
try:
do something
finally:
self.lock.release()
def interface2(self,…):
same as interface1()
…
这版代码的问题很明显,那就是每个接口函数都有相同的加锁/解锁代码,重复的代码带来的是更多的键入,更多的阅读,更多的维护,以及更多的修改,最主要的是,程序员本应集中在业务上的的精力被分散了,而且请注意,真正的业务代码在距离函数定义2次缩进处开始,即使你的显示器是宽屏,这也会带来一些阅读上的困难。
def sync(func):
def wrapper(*args,**kv):
self = args[0]
self.lock.acquire()
try:
return func(*args,**kv)
finally:
self.lock.release()
return wrapper
class Foo(object):
def __init__(self,…):
self.lock = threading.Lock()
@sync
def interface1(self,…):
do something
@sync
def interface2(self,…):
do something
…
一个装饰器函数的第一个参数是所要装饰的那个函数对象,而且装饰器函数必须返回一个函数对象。如sync函数,当其装饰interface1时,参数func的值就是interface1,返回值是wrapper,但类Foo实例的interface1被调用时,实际调用的是wrapper函数,在wrapper函数体中间接调用实际的interface1;当interface2被调用时,也调用的是wrapper函数,不过由于在装饰时func已经变成interface2,所以会间接地调用到实际的interface2函数。
class DecorateClass(object):
def decorate(self):
for name,fn in self.iter():
if not self.filter(name,fn):
continue
self.operate(name,fn)
class LockerDecorator(DecorateClass):
def __init__(self,obj,lock = threading.RLock()):
self.obj = obj
self.lock = lock
def iter(self):
return [(name,getattr(self.obj,name)) for name in dir(self.obj)]
def filter(self,name,fn):
if not name.startswith('_') and callable(fn):
return True
else:
return False
def operate(self,fn):
def locker(*args,**kv):
self.lock.acquire()
try:
return fn(*args,**kv)
finally:
self.lock.release()
setattr(self.obj,locker)
class Foo(object):
def __init__(self,…):
…
LockerDecorator(self).decorate()
def interface1(self,…):
do something
def interface2(self,…):
do something
…
对对象的功能装饰是一个更一般的功能,不仅限于为接口加锁,我用2个类来完成这一功能,DecorateClass是一个基类,只定义了遍历并应用装饰功能的算法代码(template method),LockerDecorator实现了为对象加锁的功能,其中iter是迭代器,定义了怎样遍历对象中的成员(包括数据成员和成员函数),filter是过滤器,定义了符合什么规则的成员才能成为一个接口,operate是执行函数,具体实施了为对象接口加锁的功能。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
