亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python設(shè)計(jì)模式編程中的備忘錄模式與對象池模式示例

 更新時(shí)間:2016年02月02日 16:34:41   作者:dongweiming  
這篇文章主要介紹了Python設(shè)計(jì)模式編程中的備忘錄模式與對象池模式,文中分別舉了表單和線程的相關(guān)示例,需要的朋友可以參考下

Memento備忘錄模式
備忘錄模式一個最好想象的例子:undo! 它對對象的一個狀態(tài)進(jìn)行了'快照', 在你需要的時(shí)候恢復(fù)原貌。做前端會有一個場景:你設(shè)計(jì)一個表單,當(dāng)點(diǎn)擊提交會對表單內(nèi)容 驗(yàn)證,這個時(shí)候你就要對用戶填寫的數(shù)據(jù)復(fù)制下來,當(dāng)用戶填寫的不正確或者格式不對等問題, 就可以使用快照數(shù)據(jù)恢復(fù)用戶已經(jīng)填好的,而不是讓用戶重新來一遍,不是嘛?

python的例子
這里實(shí)現(xiàn)了一個事務(wù)提交的例子

import copy

def Memento(obj, deep=False):

  # 對你要做快照的對象做快照
  state = (copy.copy if deep else copy.deepcopy)(obj.__dict__)
  def Restore():
    obj.__dict__ = state
  return Restore

class Transaction:

  deep = False
  def __init__(self, *targets):
    self.targets = targets
    self.Commit()
  # 模擬事務(wù)提交,其實(shí)就是初始化給每個對象往self.targets賦值
  def Commit(self):
    self.states = [Memento(target, self.deep) for target in self.targets]
  # 回滾其實(shí)就是調(diào)用Memento函數(shù),執(zhí)行其中的閉包,將__dict__恢復(fù)
  def Rollback(self):
    for state in self.states:
      state()

# 裝飾器的方式給方法添加這個事務(wù)的功能
def transactional(method):
  # 這里的self其實(shí)就是要保存的那個對象,和類的實(shí)例無關(guān)
  def wrappedMethod(self, *args, **kwargs):
    state = Memento(self)
    try:
      return method(self, *args, **kwargs)
    except:
      # 和上面的回滾一樣,異常就恢復(fù)
      state()
      raise
  return wrappedMethod

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 DoStuff(self):
    # 賦值成字符串,再自增長肯定會報(bào)錯的
    self.value = '1111'
    self.Increment()

if __name__ == '__main__':

  n = NumObj(-1)
  print n
  t = Transaction(n)
  try:
    for i in range(3):
      n.Increment()
      print n
    # 這里事務(wù)提交會保存狀態(tài)從第一次的-1到2
    t.Commit()
    print '-- commited'
    for i in range(3):
      n.Increment()
      print n
    n.value += 'x' # will fail
    print n
  except:
    # 回滾只會回顧到上一次comit成功的2 而不是-1
    t.Rollback()
    print '-- rolled back'
  print n
  print '-- now doing stuff ...'
  try:
    n.DoStuff()
  except:
    print '-> doing stuff failed!'
    import traceback
    traceback.print_exc(0)
    pass
  # 第二次的異?;貪Ln還是2, 整個過程都是修改NumObj的實(shí)例對象
  print n

注意
當(dāng)你要保存的狀態(tài)很大,可能會浪費(fèi)大量內(nèi)存


對象池模式
在開發(fā)中,我們總是用到一些和'池'相關(guān)的東西,比如 內(nèi)存池,連接池,對象池,線程池.. 這里說的對象池其實(shí)也就是一定數(shù)量已經(jīng)創(chuàng)建好的對象的集合。為什么要用對象池? 創(chuàng)建對象是要付出代價(jià)的(我暫時(shí)還沒有研究過底層,只說我工作中體會的), 比如pymongo就自帶線程池,這樣用完就放回到池里再被重用,豈不是節(jié)省了創(chuàng)建的花費(fèi)?

python的例子
我這里實(shí)現(xiàn)了個線程安全的簡單的對象池

import Queue
import types
import threading
from contextlib import contextmanager

class ObjectPool(object):

  def __init__(self, fn_cls, *args, **kwargs):
    super(ObjectPool, self).__init__()
    self.fn_cls = fn_cls
    self._myinit(*args, **kwargs)

  def _myinit(self, *args, **kwargs):
    self.args = args
    self.maxSize = int(kwargs.get("maxSize",1))
    self.queue = Queue.Queue()
  def _get_obj(self):
    # 因?yàn)閭鬟M(jìn)來的可能是函數(shù),還可能是類
    if type(self.fn_cls) == types.FunctionType:
      return self.fn_cls(self.args)
    # 判斷是經(jīng)典或者新類
    elif type(self.fn_cls) == types.ClassType or type(self.fn_cls) == types.TypeType:
      return apply(self.fn_cls, self.args)
    else:
      raise "Wrong type"

  def borrow_obj(self):
    # 這個print 沒用,只是在你執(zhí)行的時(shí)候告訴你目前的隊(duì)列數(shù),讓你發(fā)現(xiàn)對象池的作用
    print self.queue._qsize()
    # 要是對象池大小還沒有超過設(shè)置的最大數(shù),可以繼續(xù)放進(jìn)去新對象
    if self.queue.qsize()<self.maxSize and self.queue.empty():
      self.queue.put(self._get_obj())
    # 都會返回一個對象給相關(guān)去用
    return self.queue.get() 
  # 回收
  def recover_obj(self,obj):
    self.queue.put(obj)

# 測試用函數(shù)和類
def echo_func(num):
  return num

class echo_cls(object):
  pass

# 不用構(gòu)造含有__enter__, __exit__的類就可以使用with,當(dāng)然你可以直接把代碼放到函數(shù)去用
@contextmanager
def poolobj(pool):
  obj = pool.borrow_obj()
  try:
    yield obj
  except Exception, e:
    yield None
  finally:
    pool.recover_obj(obj)

obj = ObjectPool(echo_func, 23, maxSize=4)
obj2 = ObjectPool(echo_cls, maxSize=4)

class MyThread(threading.Thread):

  def run(self):
    # 為了實(shí)現(xiàn)效果,我搞了個簡單的多線程,2個with放在一個地方了,只為測試用
    with poolobj(obj) as t:
      print t
    with poolobj(obj2) as t:
      print t

if __name__ == '__main__':
  threads = []
  for i in range(200):
    t = MyThread()
    t.start()
    threads.append(t)
  for t in threads:
    t.join(True)

相關(guān)文章

  • C#實(shí)現(xiàn)Excel動態(tài)生成PivotTable

    C#實(shí)現(xiàn)Excel動態(tài)生成PivotTable

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)Excel動態(tài)生成PivotTable的相關(guān)方法,感興趣的小伙伴們可以參考一下
    2016-04-04
  • 一個讀寫csv文件的C#類

    一個讀寫csv文件的C#類

    這篇文章主要為大家詳細(xì)介紹了一個讀寫csv文件的C#類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • C#委托與匿名委托詳解

    C#委托與匿名委托詳解

    這篇文章主要為大家詳細(xì)介紹了C#委托與匿名委托的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • 實(shí)例詳解C#實(shí)現(xiàn)http不同方法的請求

    實(shí)例詳解C#實(shí)現(xiàn)http不同方法的請求

    本篇文章給大家分享了C#實(shí)現(xiàn)http不同方法的請求的相關(guān)知識點(diǎn)以及實(shí)例代碼,有需要的朋友參考下。
    2018-07-07
  • 詳解c#讀取XML的實(shí)例代碼

    詳解c#讀取XML的實(shí)例代碼

    XML文件是一種常用的文件格式,本篇文章主要介紹了c#讀取XML的實(shí)例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • Unity3D實(shí)現(xiàn)待機(jī)狀態(tài)圖片循環(huán)淡入淡出

    Unity3D實(shí)現(xiàn)待機(jī)狀態(tài)圖片循環(huán)淡入淡出

    這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)待機(jī)狀態(tài)圖片循環(huán)淡入淡出,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C#往線程里傳遞參數(shù)的方法小結(jié)

    C#往線程里傳遞參數(shù)的方法小結(jié)

    這篇文章主要介紹了C#往線程里傳參數(shù)的方法小結(jié)的相關(guān)資料,還給大家簡單說明下傳參的兩種方式,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • WPF實(shí)現(xiàn)動畫效果(四)之緩動函數(shù)

    WPF實(shí)現(xiàn)動畫效果(四)之緩動函數(shù)

    這篇文章介紹了WPF實(shí)現(xiàn)動畫效果之緩動函數(shù),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • VS2010寫的程序在自己電腦可以運(yùn)行、其他電腦上不能運(yùn)行的解決方案

    VS2010寫的程序在自己電腦可以運(yùn)行、其他電腦上不能運(yùn)行的解決方案

    自己用Visual Studio 2010 旗艦版寫了一個軟件,在自己電腦上運(yùn)行完全沒有問題,但是拷貝到其他人電腦上之后不管雙擊還是以管理身份運(yùn)行,均沒有反應(yīng),進(jìn)程管理器中相關(guān)進(jìn)程也只是一閃而過
    2013-04-04
  • C#實(shí)現(xiàn)封裝常用Redis工具類的示例代碼

    C#實(shí)現(xiàn)封裝常用Redis工具類的示例代碼

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)封裝常用Redis工具類的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03

最新評論