python 设计模式-装饰器模式

装饰器模式实现起来跟代理模式差多,其实可以是一样的,看你把它置于什么场景。代理模式侧重于隔离客户与被代理者,通过代理者控制访问被代理者的权限,而装饰器模式侧重于给被装饰的对象提供附加的功能,例如加上日志功能。python 语法层面就提供了装饰器,足以说明装饰器模式的重要性,这里我们就直接介绍python的装饰器吧。

先看看函数装饰器:

def work_wrapper(w):
    def func(*args, **kwargs):
        print('logging start ...')
        w(*args, **kwargs)
        print('logging end ...')
    return func


@work_wrapper
def work():
    print('working')


if __name__ == '__main__':
    work()

输出:

logging start ...
working
logging end ...

@符号是装饰器的标志,函数work上加一行@work_wrapper的意思是 work = work_wrapper(work)。装饰器可以叠加,我们修改下:

def work_wrapper_a(w):
    def func(*args, **kwargs):
        print('a logging start ...')
        w(*args, **kwargs)
        print('a logging end ...')
    return func

def work_wrapper_b(w):
    def func(*args, **kwargs):
        print('b logging start ...')
        w(*args, **kwargs)
        print('b logging end ...')
    return func


@work_wrapper_b
@work_wrapper_a
def work():
    print('working')


if __name__ == '__main__':
    work()

输出

b logging start ...
a logging start ...
working
a logging end ...
b logging end ...

装饰器还可以带参数,如下:

def work_para_wrapper(work_times): 
    def work_wrapper(w):
        def func(*args, **kwargs):
            print('logging start ...')
            [w(*args, **kwargs) for i in range(work_times)]
            print('logging end ...')
        return func
    return work_wrapper


@work_para_wrapper(3)
def work():
    print('working')


if __name__ == '__main__':
    work()

其实跟不带参数的装饰器原理一样,work_para_wrapper(3)会返回一个不带参数装饰器。不但函数可以应用装饰器,类也可以,看下面例子:

def worker_wrapper(cls):
    class WorkerEnhanced(cls):
        def learn(self):
            print('learning new things, {}'.format(self._name))

    return WorkerEnhanced


@worker_wrapper
class Worker:
    def __init__(self, name):
        self._name = name
    
    def work(self):
        print('working')


if __name__ == '__main__':
    w = Worker('Jack')
    print(type(w))
    w.learn()

输出

<class '__main__.worker_wrapper.<locals>.WorkerEnhanced'>
learning new things, Jack

另外,利用类的魔术方法 __call__,类也可以作为装饰器。

class WorkerEnhanced:
    def __init__(self, worker):
        self._worker = worker()

    def __call__(self, name):
        self._worker.Name = name
        return self 
    
    def learn(self):
        print('{} is learning new things'.format(self._worker.Name))
        
    def work(self):
        self._worker.work()


@WorkerEnhanced
class Worker:
    
    def __init__(self, name=None):
        self._name = name
        
    @property
    def Name(self):
        return self._name
    
    @Name.setter
    def Name(self, val):
        self._name = val

    def work(self):
        print('{} is working'.format(self._name))


if __name__ == '__main__':
    w = Worker('Jack')
    print(type(w))
    w.work()
    w.learn()

输出:

<class '__main__.WorkerEnhanced'>
Jack is working
Jack is learning new things

这个例子没什么意义,只是为了说明下怎么使用类来装饰类。最后强调一下,不论是函数装饰器还是类装饰器,原理都是同一个 @ d e c o r a t e t o _ b e _ d e c o r a t e d \frac{@decorate}{to\_be\_decorated} to_be_decorated@decorate ==> t o _ b e _ d e c o r a t e d = d e c o r a t e ( t o _ b e _ d e c o r a t e d ) to\_be\_decorated = decorate(to\_be\_decorated) to_be_decorated=decorate(to_be_decorated)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值