Python设计模式(六)【职责链模式】

来源:互联网 发布:北大知乎 编辑:程序博客网 时间:2024/05/22 13:33

周末补充知识,编程哲学

"""职责链模式"""import timeimport osimport sysfrom contextlib import contextmanager"""象处理者:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常是一个抽象类或接口。"""class Handler:    def __init__(self, successor=None):        self._successor = successor    def handle(self, request):        res = self._handle(request)        if not res:            self._successor.handle(request)    def _handle(self, request):        raise NotImplementedError('必须提供子类实现.')#实际处理者1class ConcreteHandler1(Handler):    def _handle(self, request):        if 0 < request <= 10:            print('请求{} 被处理程序1 处理'.format(request))            return True#实际处理者2class ConcreteHandler2(Handler):    def _handle(self, request):        if 10 < request <= 20:            print('请求{} 被处理程序2 处理'.format(request))            return True#实际处理者3class ConcreteHandler3(Handler):    def _handle(self, request):        if 20 < request <= 30:            print('请求{} 被处理程序3 处理'.format(request))            return True#默认处理者class DefaultHandler(Handler):    def _handle(self, request):        print('职责链已到终点,没有处理程序处理{}'.format(request))        return True"""   这里用到了yield,然后就可以直接将接收到的数据打印出来了。当然,还有一个值得注意的地方是用到了一个@coroutine的decorator。   因为在每次使用coroutine之前我们需要调用一次target.next()或者target.send(None)来初始化它。这样我们使用的时候很容易忘记这一步,   一种办法就是定义好一个这样的decorator,然后每次将这个decorator加上就保证这一步被执行了。@coroutine decorator的定义如下:   如果是函数定义中参数前的*表示的是将调用时的多个参数放入元组中,**则表示将调用函数时的关键字参数放入一个字典中    如定义以下函数    def func(*args):print(args)    当用func(1,2,3)调用函数时,参数args就是元组(1,2,3)    定义以下函数    def func(**args):print(args)    当用func(a=1,b=2)调用函数时,参数args将会是字典{'a':1,'b':2}"""def coroutine(func):    def start(*args, **kwargs):        cr = func(*args, **kwargs)        next(cr)        return cr    return start"""coroutine是一个实现多个任务之间互相切换的手段,它相当于一种将一个当前执行的结果传递给另外一个过程。和generator的使用过程比起来,它更像是一种“推”模式。因为我们要使用一个coroutine的时候,必然是需要有其它的过程send数据过来。因为yield的过程有点类似于一个操作系统里中断的概念,它相当于将一个进程的当前执行过程暂停,然后跳转到另外一个过程。这种过程和我们传统通过栈实现的子过程调用很不一样,所以表面上理解起来还是有点困难。因为coroutine相当于一个数据的消费者协同程序(协程)一般来说是指这样的函数:    彼此间有不同的局部变量、指令指针,但仍共享全局变量;    可以方便地挂起、恢复,并且有多个入口点和出口点;    多个协同程序间表现为协作运行,如A的运行过程中需要B的结果才能继续执行。"""@coroutinedef coroutine1(target):    while True:        #接收行        request = yield        if 0 < request <= 10:            print('请求{}在被协同程序1 处理 '.format(request))        else:            target.send(request)@coroutinedef coroutine2(target):    while True:        request = yield        if 10 < request <= 20:            print('请求{}在被协同程序2 处理'.format(request))        else:            target.send(request)@coroutinedef coroutine3(target):    while True:        request = yield        if 20 < request <= 30:            print('请求{}在被协同程序3 处理'.format(request))        else:            target.send(request)@coroutinedef default_coroutine():    while True:        request = yield        print('职责链的终点,没有协同程序处理{}'.format(request))"""客户端协程"""class ClientCoroutine:    def __init__(self):        self.target = coroutine1(coroutine3(coroutine2(default_coroutine())))    def delegate(self, requests):        for request in requests:            """发送到下一个阶段"""            self.target.send(request)def timeit(func):    def count(*args, **kwargs):        start = time.time()        res = func(*args, **kwargs)        count._time = time.time() - start        return res    return count"""上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__() 和 __exit__() 方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。"""@contextmanagerdef suppress_stdout():    try:        stdout, sys.stdout = sys.stdout, open(os.devnull, 'w')        yield    finally:        sys.stdout = stdoutclass Client:    def __init__(self):        self.handler = ConcreteHandler1(ConcreteHandler3(ConcreteHandler2(DefaultHandler())))    def delegate(self, requests):        for request in requests:            self.handler.handle(request)if __name__ == "__main__":    client1 = Client()    client2 = ClientCoroutine()    requests = [2, 5, 14, 22, 18, 3, 35, 27, 20]    client1.delegate(requests)    print('-' * 30)    client2.delegate(requests)    requests *= 10000    #数组增加到9W个    #print(requests)    client1_delegate = timeit(client1.delegate)    client2_delegate = timeit(client2.delegate)    with suppress_stdout():        client1_delegate(requests)        client2_delegate(requests)    # 让我们检查哪个速度更快    print("类处理时间:",client1_delegate._time,"协同程序处理时间:",client2_delegate._time)

结果如图:

这里写图片描述

0 0
原创粉丝点击