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
def set_need_tick(self, is_need):
self.need_tick = is_need def tick(self):
if self.need_tick:
self.do_tick() # do_tick 需要做大量的检查,较为耗时
def dummy_tick(self):
pass
def set_need_tick(self, is_need):
if is_need:
self.tick = self.do_tick
else:
self.tick = self.dummy_tick
Second
class cached_property(object):
""" A property that is only computed once per instance and then replaces
itself with an ordinary attribute. Deleting the attribute resets the
property. """ def __init__(self, func):
update_wrapper(self, func)
self.func = func def __get__(self, obj, cls):
if obj is None: return self
value = obj.__dict__[self.func.__name__] = self.func(obj)
return value
def set_property_dirty(self, property_name):
self.__dict__.pop(property_name, None)
在需要的时候调用这个设置函数就行了,在这个例子中,并没有对某个属性的设置和检查,但配合之前的cached_property,作用是很明显的:缓存计算结果,需要的时候重新计算。下面是完整测试代码
import functools, time
class cached_property(object):
""" A property that is only computed once per instance and then replaces
itself with an ordinary attribute. Deleting the attribute resets the
property. """ def __init__(self, func):
functools.update_wrapper(self, func)
self.func = func def __get__(self, obj, cls):
if obj is None: return self
value = obj.__dict__[self.func.__name__] = self.func(obj)
return value class TestClz(object):
@cached_property
def complex_calc(self):
print 'very complex_calc'
return sum(range(100)) def __set_property_dirty(self, property_name = 'complex_calc'):
self.__dict__.pop(property_name, None) def some_action_effect_property(self):
self.__set_property_dirty() if __name__=='__main__':
t = TestClz()
print '>>> first call'
print t.complex_calc
print '>>> second call'
print t.complex_calc
print '>>>third call'
t.some_action_effect_property()
print t.complex_calc
cache property and dirty
Third
Fourth
Fifth
适用场景:
使用条件:
注意事项:
Dirty Flag 模式及其应用的更多相关文章
- lazy ideas in programming
lazy形容词,懒惰的,毫无疑问是一个贬义词.但是,对于计算机领域,lazy却是非常重要的优化思想:把任务推迟到必须的时刻,好处是避免重复计算,甚至不计算.本文的目的是抛砖引玉,总结一些编程中的laz ...
- python性能优化
注意:本文除非特殊指明,”python“都是代表CPython,即C语言实现的标准python,且本文所讨论的是版本为2.7的CPython. python为什么性能差: 当我们提到一门编程语言的 ...
- lazy ideas in programming(编程中的惰性思想)
lazy形容词,懒惰的,毫无疑问是一个贬义词.但是,对于计算机领域,lazy却是非常重要的优化思想:把任务推迟到必须的时刻,好处是避免重复计算,甚至不计算.本文的目的是抛砖引玉,总结一些编程中的laz ...
- Redis——学习之路二(初识redis服务器命令)
上一章我们已经知道了如果启动redis服务器,现在我们来学习一下,以及如何用客户端连接服务器.接下来我们来学习一下查看操作服务器的命令. 服务器命令: 1.info——当前redis服务器信息 s ...
- 【redis使用全解析】常见运维操作
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.1 启动 1.1.1 启动redis $ redis-server redis.conf 常见选项: ./r ...
- Unity ShaderLab学习总结
http://www.jianshu.com/p/7b9498e58659 Unity ShaderLab学习总结 Why Bothers? 为什么已经有ShaderForge这种可视化Shader编 ...
- Inside of Jemalloc
INSIDE OF JEMALLOCThe Algorithm and Implementation of Jemalloc author: vector03mail: mmzsmm@163.co ...
- cocod2d-x 之 CCDirector、CCScene、CCSprite
CCDirector是控制游戏流程的主要组件. typedef enum { /// sets a 2D projection (orthogonal projection)2D投机模式 kCCDir ...
- 查看Redis信息和状态
原文转自:http://redisdoc.com/server/info.html INFO [section] 以一种易于解释(parse)且易于阅读的格式,返回关于 Redis 服务器的各种信息和 ...
随机推荐
- CSU 1515 Sequence
莫队算法+map #include<cstdio> #include<cstring> #include<cmath> #include<map> #i ...
- URL与String转换
NSString *str = @"www.baidu.com"; NSURL *URL = [NSURL URLWithString:str]; //string>url ...
- MapReduce 多表连接
题目描述: 现在有两个文件,1为存放公司名字和城市ID,2为存放城市ID和城市名 表一: factoryname,addressed Beijing Red Star,1 Shenzhen Thund ...
- 基于STM32的uCOS-II移植详解
百度:基于STM32的uCOS-II移植详解 源:基于STM32的uCOS-II移植详解
- iOS开发 调用系统相机和相册
调用系统相机和相册 (iPad,iPhone)打开相机:(iPad,iPhone)//先设定sourceType为相机,然后判断相机是否可用(ipod)没相机,不可用将sourceType设定为相片库 ...
- Android项目文件结构
一.Project项目结构 app/build/ app模块build编译输出的目录 app/build.gradle app模块的gradle编译文件 app/app.iml app模块的配置文件 ...
- iOS 之 网络 NSURLSession
NSURLSession相比NSURLConnection功能更强大,是更上层的网络封装.相比而言,普通应用场景下NSURLSession没有什么优势,但是,在程序切换到后台的情况下,NSURLSes ...
- 三 APPIUM Android自动化 测试初体验
1.创建一个maven项目 成功新建工程: 编辑pom.xml,在<dependencies></dependencies>下添加appium相关依赖: <depende ...
- Voilin 与 乐谱
小提琴属于高音乐器,所以它使用的是高音谱号: 用音的时候,线不够用,那就得上加线,或下加线. 小提琴的弦对应的五线谱的位置为: 第四弦,对应五线谱的下加两条线的下面 第三弦,对应五线谱的第一线的下面 ...
- Angular - -ngKeydown/ngKeypress/ngKeyup 键盘事件和鼠标事件
ngKeydown/ngKeypress/ngKeyup 该指令在按键按下/按键按下/按键松开时执行指定表达式. ngKeydown和ngKeypress略有不同,目前的测试是ngKeypress针对 ...