首页 > 代码库 > Dirty Flag 模式及其应用
Dirty Flag 模式及其应用
之前在开发中就发现“dirty”是一种不错的解决方案:可以用来延缓计算或者避免不必要的计算。后来在想,这应该也算一种设计模式吧,于是搜索“Dirty设计模式”,没有什么结果,然后换成英文“Dirty design pattern”,搜到了《game programming patterns》这本电子书。书中介绍了Dirty Flag 模式在游戏客户端的应用场景,如果英文不好,这里也有中文翻译。本文结合几个具体的例子,介绍什么是Dirty Flag 模式,并分析该模式的适用场景以及使用注意事项。
什么是Dirty Flag:
简单来说,就是用一个标志位(flag)来表示一组数据的状态,这些数据要么是用来计算,或者用来需要同步。在满足条件的时候设置标志位,然后需要的时候检查(check)标志位。如果设置了标志位,那么表示这组数据处于dirty状态,这个时候需要重新计算或者同步。如果flag没有被设置,那么可以不计算(或者利用缓存的计算结果)。另外,在两次check之间,即使有多次标志位的设置,也只需要计算一次。
因此,Dirty Flag模式的本质作用在于:延缓计算或数据同步,甚至减少无谓的计算或者同步。计算比较容易理解,对于同步,后面也会给出例子。在后面的描述中,除非特殊说明,计算也包含了同步。
Dirty Flag使用实例:
首先,《game programming pattern》中的例子非常形象生动,图文并茂,建议直接阅读原文,本文不再复述。接下来介绍几个其他的例子。
First
1 def set_need_tick(self, is_need): 2 self.need_tick = is_need 3 4 def tick(self): 5 if self.need_tick: 6 self.do_tick() # do_tick 需要做大量的检查,较为耗时
1 def dummy_tick(self): 2 pass 3 def set_need_tick(self, is_need): 4 if is_need: 5 self.tick = self.do_tick 6 else: 7 self.tick = self.dummy_tick
Second
1 class cached_property(object): 2 """ A property that is only computed once per instance and then replaces 3 itself with an ordinary attribute. Deleting the attribute resets the 4 property. """ 5 6 def __init__(self, func): 7 update_wrapper(self, func) 8 self.func = func 9 10 def __get__(self, obj, cls): 11 if obj is None: return self 12 value = http://www.mamicode.com/obj.__dict__[self.func.__name__] = self.func(obj) 13 return value
1 def set_property_dirty(self, property_name): 2 self.__dict__.pop(property_name, None)
在需要的时候调用这个设置函数就行了,在这个例子中,并没有对某个属性的设置和检查,但配合之前的cached_property,作用是很明显的:缓存计算结果,需要的时候重新计算。下面是完整测试代码
1 import functools, time 2 class cached_property(object): 3 """ A property that is only computed once per instance and then replaces 4 itself with an ordinary attribute. Deleting the attribute resets the 5 property. """ 6 7 def __init__(self, func): 8 functools.update_wrapper(self, func) 9 self.func = func 10 11 def __get__(self, obj, cls): 12 if obj is None: return self 13 value = http://www.mamicode.com/obj.__dict__[self.func.__name__] = self.func(obj) 14 return value 15 16 class TestClz(object): 17 @cached_property 18 def complex_calc(self): 19 print ‘very complex_calc‘ 20 return sum(range(100)) 21 22 def __set_property_dirty(self, property_name = ‘complex_calc‘): 23 self.__dict__.pop(property_name, None) 24 25 def some_action_effect_property(self): 26 self.__set_property_dirty() 27 28 29 30 if __name__==‘__main__‘: 31 t = TestClz() 32 print ‘>>> first call‘ 33 print t.complex_calc 34 print ‘>>> second call‘ 35 print t.complex_calc 36 print ‘>>>third call‘ 37 t.some_action_effect_property() 38 print t.complex_calc
Third
Fourth
Fifth
适用场景:
使用条件:
注意事项:
Dirty Flag 模式及其应用