您的位置:首页 > 编程语言 > Python开发

设计模式-备忘录模式-memento-python??

2017-08-10 19:29 501 查看

def

在不破坏封装性的前提下, 捕获一个对象的内部状态, 并在该对象之外保存这个状态。 这样以后就可将该对象恢复到原先保存的状态。

usage

● 需要保存和恢复数据的相关状态场景。

● 提供一个可回滚(rollback) 的操作; 比如Word中的CTRL+Z组合键, IE浏览器中的后退按钮, 文件管理器上的backspace键等。

● 需要监控的副本场景中。 例如要监控一个对象的属性, 但是监控又不应该作为系统的主业务来调用, 它只是边缘应用, 即使出现监控不准、 错误报警也影响不大, 因此一般的做法是备份一个主线程中的对象, 然后由分析程序来分析。

● 数据库连接的事务管理就是用的备忘录模式, 想想看, 如果你要实现一个JDBC驱动, 你怎么来实现事务? 还不是用备忘录模式嘛

code

from copy import copy
from copy import 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(object):
"""A transaction guard.
This is, in fact, just syntactic sugar 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):
"""Adds transactional semantics to methods. Methods decorated  with
@Transactional will rollback to entry-state upon exceptions.
"""

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'  # <- invalid value
self.increment()  # <- will fail and rollback

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'  # will fail
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)

### OUTPUT ###
# <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 "memento.py", line 97, in <module>
#     num_obj.do_stuff()
#   File "memento.py", line 52, in transaction
#     raise e
#   File "memento.py", line 49, in transaction
#     return self.method(obj, *args, **kwargs)
#   File "memento.py", line 70, in do_stuff
#     self.increment()     # <- will fail and rollback
#   File "memento.py", line 65, in increment
#     self.value += 1
# TypeError: Can't convert 'int' object to str implicitly
# <NumObj: 2>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式