设计模式-责任链模式-chain-python

来源:互联网 发布:大数据时代保险变革研 编辑:程序博客网 时间:2024/06/06 07:34

def

使多个对象都有机会处理请求, 从而避免了请求的发送者和接受者之间的耦合关系。 将这些对象连成一条链, 并沿着这条链传递该请求, 直到有对象处理它为止。

usage

责任链模式非常显著的优点是将请求和处理分开。 请求者可以不用知道是谁处理的, 处理者可以不用知道请求的全貌(例如在J2EE项目开发中, 可以剥离出无状态Bean由责任链处理) , 两者解耦, 提高系统的灵活性。

code

class Handler(object):    __metaclass__ = abc.ABCMeta    def __init__(self, successor=None):        self._successor = successor    def handle(self, request):        res = self._handle(request)        if not res:            self._successor.handle(request)    @abc.abstractmethod    def _handle(self, request):        raise NotImplementedError('Must provide implementation in subclass.')class ConcreteHandler1(Handler):    def _handle(self, request):        if 0 < request <= 10:            print('request {} handled in handler 1'.format(request))            return Trueclass ConcreteHandler2(Handler):    def _handle(self, request):        if 10 < request <= 20:            print('request {} handled in handler 2'.format(request))            return Trueclass ConcreteHandler3(Handler):    def _handle(self, request):        if 20 < request <= 30:            print('request {} handled in handler 3'.format(request))            return Trueclass DefaultHandler(Handler):    def _handle(self, request):        print('end of chain, no handler for {}'.format(request))        return Trueclass Client(object):    def __init__(self):        self.handler = ConcreteHandler1(            ConcreteHandler3(ConcreteHandler2(DefaultHandler())))    def delegate(self, requests):        for request in requests:            self.handler.handle(request)def coroutine(func):    def start(*args, **kwargs):        cr = func(*args, **kwargs)        next(cr)        return cr    return start@coroutinedef coroutine1(target):    while True:        request = yield        if 0 < request <= 10:            print('request {} handled in coroutine 1'.format(request))        else:            target.send(request)@coroutinedef coroutine2(target):    while True:        request = yield        if 10 < request <= 20:            print('request {} handled in coroutine 2'.format(request))        else:            target.send(request)@coroutinedef coroutine3(target):    while True:        request = yield        if 20 < request <= 30:            print('request {} handled in coroutine 3'.format(request))        else:            target.send(request)@coroutinedef default_coroutine():    while True:        request = yield        print('end of chain, no coroutine for {}'.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@contextmanagerdef suppress_stdout():    try:        stdout, sys.stdout = sys.stdout, open(os.devnull, 'w')        yield    finally:        sys.stdout = stdoutif __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    client1_delegate = timeit(client1.delegate)    client2_delegate = timeit(client2.delegate)    with suppress_stdout():        client1_delegate(requests)        client2_delegate(requests)    # lets check what is faster    print(client1_delegate._time, client2_delegate._time)### OUTPUT #### request 2 handled in handler 1# request 5 handled in handler 1# request 14 handled in handler 2# request 22 handled in handler 3# request 18 handled in handler 2# request 3 handled in handler 1# end of chain, no handler for 35# request 27 handled in handler 3# request 20 handled in handler 2# ------------------------------# request 2 handled in coroutine 1# request 5 handled in coroutine 1# request 14 handled in coroutine 2# request 22 handled in coroutine 3# request 18 handled in coroutine 2# request 3 handled in coroutine 1# end of chain, no coroutine for 35# request 27 handled in coroutine 3# request 20 handled in coroutine 2# (0.2369999885559082, 0.16199994087219238)
阅读全文
0 0
原创粉丝点击