Python设计模式(二十一)【备忘录模式】

来源:互联网 发布:短信轰炸机软件 编辑:程序博客网 时间:2024/06/05 15:51

相信是成功的起点,坚持是成功的终点。

# -*- coding: utf-8 -*-from copy import copy, deepcopydef memento(obj, deep=False):    state = deepcopy(obj.__dict__) if deep else copy(obj.__dict__)    def restore():        obj.__dict__.clear()        obj.__dict__.update(state)    return restoreclass Transaction:    """一个事务守护.      这一点,事实上, 就是语法糖 around a memento closure.    """    deep = False    states = []    def __init__(self, deep, *targets):        self.deep = deep        self.targets = targets        self.commit()    def commit(self):        self.states = [memento(target, self.deep) for target in self.targets]    def rollback(self):        for a_state in self.states:            a_state()class Transactional(object):    """    添加事务语义方法。方法用@Transactional装饰,在异常时将回滚到进入状态。    """    def __init__(self, method):        self.method = method    def __get__(self, obj, T):        def transaction(*args, **kwargs):            state = memento(obj)            try:                return self.method(obj, *args, **kwargs)            except Exception as e:                state()                raise e        return transactionclass NumObj(object):    def __init__(self, value):        self.value = value    def __repr__(self):        return '<%s: %r>' % (self.__class__.__name__, self.value)    def increment(self):        self.value += 1    @Transactional    def do_stuff(self):        self.value = '1111'  # <- 无效的值        self.increment()  # <- 将失败并回滚if __name__ == '__main__':    num_obj = NumObj(-1)    print(num_obj)    a_transaction = Transaction(True, num_obj)    try:        for i in range(3):            num_obj.increment()            print(num_obj)        a_transaction.commit()        print('-- committed')        for i in range(3):            num_obj.increment()            print(num_obj)        num_obj.value += 'x'  # 将失败        print(num_obj)    except Exception as e:        a_transaction.rollback()        print('-- rolled back')    print(num_obj)    print('-- now doing stuff ...')    try:        num_obj.do_stuff()    except Exception as e:        print('-> doing stuff failed!')        import sys        import traceback        traceback.print_exc(file=sys.stdout)    print(num_obj)

结果:

<NumObj: -1><NumObj: 0><NumObj: 1><NumObj: 2>-- committed<NumObj: 3><NumObj: 4><NumObj: 5>-- rolled back<NumObj: 2>-- now doing stuff ...-> doing stuff failed!Traceback (most recent call last):  File "mementoTest.py", line 96, in <module>    num_obj.do_stuff()  File "mementoTest.py", line 51, in transaction    raise e  File "mementoTest.py", line 48, in transaction    return self.method(obj, *args, **kwargs)  File "mementoTest.py", line 69, in do_stuff    self.increment()  # <- 将失败并回滚  File "mementoTest.py", line 64, in increment    self.value += 1TypeError: Can't convert 'int' object to str implicitly<NumObj: 2>
0 0