邓际锋ID:soloist
83631次访问,排名1122好友1人,关注者2
soloist的文章
原创 39 篇
翻译 0 篇
转载 0 篇
评论 189 篇
soloist的公告
欢迎吹毛求疵,感谢您对任何错误的指正,包括技术的、语法的、用词的、标点的、典故的、引用资料的……
最近评论
qingbai:lua绝对是个好东西。但国内除了java就是.net,其他东西没法活。因为程序员得工作,得吃饭。国内有哪家公司用lua?唉没办法呀。国外是一片繁荣,“百家争鸣”,国内是“青一色”的java和.net!无奈!
zhangyilan:尽管没有在实际代码的编写中碰到这个问题,不过也先学习一下,免得出现问题了搞出清楚情况。
ddrmsdos:这篇文章写的太好了,分析的非常仔细,以前常常碰到这类问题,终于解了我多年的心头之患......
ollydbg23:楼主的这篇文章写的非常好啊!
我看了以后,还是挺有收获感的,多谢多谢!
我也是对汇编,c++的比较感兴趣,有空可以交流一下!
w2001:写得很好
文章分类
收藏
    相册
    好博链接
    C++罗浮宫
    cpper
    fixopen
    fmddlmyy
    neoragex2002
    whinah
    云风
    梦想风暴
    沉思者
    许式伟
    负暄琐话
    辣子鸡丁
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 如何实现每个对象只执行一次的例程收藏

    新一篇: 一颗璀璨的月光宝石——Lua | 旧一篇: 央视采访吴文俊先生

        对象是数据和行为的有机结合体,每一个对象实例保存的数据都是自身特有的信息,而其中的一些数据是需要经过计算或处理才能得到的,有时候这种计算的量还不小。因此对于那些在整个对象生命周期都不会改变的数据而言,每次为了获取它们而重复执行的计算就是一个大大的浪费。一个改进的方案是:在对象创建时执行相应的动作以预先计算好那些稳定的数据并保存在内部,以后需要的话就直接返回这些预先算好的数据。这听起来是不错,但有没有问题呢?

        让我们假设有一类名为COMPANY的对象,它们都有代表历史交易信息的stock_history属性,对应的数据非常庞大并被保存在数据库中,这些信息只有从数据库载入到内存后才能使用。而实际情况是,该类对象的大部分使用者可能仅仅利用它们做些简单的操作,并不关心甚至压根儿就不知道还可以取得历史交易信息,但他们仍然不得不(在对象创建时)承担相应的计算负担,糊里糊涂地做了冤大头。所以为了最广大人民群众的根本利益,要站在讲政治的高度坚决贯彻“不使用就不掏钱”和“别重复肮脏活儿”的原则,想人民之所想,急人民之所急,为群众送去一种特殊的例程,它的功能体只会在某个对象首次调用时执行,其后相同对象进行的所有调用都不重复执行计算而直接返回第一次计算得出的结果。按照严肃的科学黑话来说,这就是典型的“按需计算”(computing on demand)。

        下面以Lua语言为例,设计了一个简洁的once per object机制。

    ONCE_PER_OBJECT = {}
    ONCE_PER_OBJECT.__index = ONCE_PER_OBJECT

    -- 创建一个对每个对象只执行一次的例程,target是针对的对象,func是只执行一次的函数。
    -- 不要惊慌,Lua里没有真正的面向对象,但函数可是一等公民。
    function ONCE_PER_OBJECT.new(target,func)
       local o = {}
       o.target = target
       o.computed = false
       o.routine = func
       o.result = 0
       setmetatable(o,ONCE_PER_OBJECT)
       return o
    end

    -- 按需执行once per object例程,并返回相应的值
    function ONCE_PER_OBJECT:value(...)
       if self.computed then
          print("So easy, data has been computed!")
          return self.result
       else
          self.result = self.routine(self.target,...)
          self.computed = true
          return self.result
       end
    end

    COMPANY = {}
    COMPANY.__index = COMPANY

    --真正执行从数据库载入历史信息的函数
    local function load_stock_history(company)
       print("Loading "..company.name..
             " company's data from database, fucking dirty work!")
       return "I am from database!"
    end

    -- 给出公司名字,创建一个COMPANY对象
    function COMPANY.new(name)
       local o = {}
       o.name = name
       o.stock_history = ONCE_PER_OBJECT.new(o,load_stock_history)
       setmetatable(o,COMPANY)
       return o
    end

    -- 创建一个叫Microsoft的COMPANY对象
    ms = COMPANY.new("Microsoft")
    -- 第一次读取ms的历史信息
    print(ms.stock_history:value())
    -- 第二次读取
    print(ms.stock_history:value())
    -- 第三次读取
    print(ms.stock_history:value())

        执行上面的代码,输出如下:

    Loading Microsoft company's data from database, fucking dirty work!
    I am from database!
    So easy, data has been computed!
    I am from database!
    So easy, data has been computed!
    I am from database!

        很显然,只有第一次读取stock_history才真的去找数据库了,随后均是轻松地返回已计算好的值。

        本文所演示的机制并不复杂,关键是计算(本例表现为函数)要能象对象一样传来传去,这对诸如Lua一类的函数是一等值(first-class value)的动态语言来说根本没有问题,而对于那些静态面向对象语言就需要有良好的delegate或者agent机制的支持。在这方面做得最好的当属Eiffel语言,它的agent机制为语言引入了强大的函数式特性,而本文的思路正是来自于Eiffel语言手册中《Agents,iterators and introspection》一章

    发表于 @ 2006年07月25日 00:23:00|评论(loading...)|编辑

    新一篇: 一颗璀璨的月光宝石——Lua | 旧一篇: 央视采访吴文俊先生

    评论

    #Net_Ghost 发表于2006-07-25 12:37:00  IP: 202.118.4.*
    似乎可以采用Singleton模式,在构造函数中作访问数据库的操作,但是构造函数中要是返回失败就惨了 赫赫
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © soloist