关闭

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

标签: python设计模式
1317人阅读 评论(0) 收藏 举报
分类:

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

# -*- coding: utf-8 -*-
from copy import copy, deepcopy

def memento(obj, deep=False):
    state = deepcopy(obj.__dict__) if deep else copy(obj.__dict__)

    def restore():
        obj.__dict__.clear()
        obj.__dict__.update(state)

    return restore

class 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 transaction


class 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 += 1
TypeError: Can't convert 'int' object to str implicitly
<NumObj: 2>
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:845481次
    • 积分:12199
    • 等级:
    • 排名:第1224名
    • 原创:296篇
    • 转载:380篇
    • 译文:52篇
    • 评论:86条
    博客专栏
    文章分类
    打赏
    如果你觉得我的文章对您有用,请随意打赏。 微信 支付宝