Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 缓存计算值的方法_Delphi_Oop_Caching_Delphi 2006 - Fatal编程技术网

Delphi 缓存计算值的方法

Delphi 缓存计算值的方法,delphi,oop,caching,delphi-2006,Delphi,Oop,Caching,Delphi 2006,在我们正在处理的Delphi应用程序中,我们有一个相关对象的大结构。这些对象的某些属性具有在运行时计算的值,我正在寻找一种方法来缓存结果,以便进行更密集的计算。我使用的一种方法是在第一次计算时将值保存在私有成员中。下面是一个简短的例子: unit Unit1; interface type TMyObject = class private FObject1, FObject2: TMyOtherObject; FMyCalculatedValue: Integer;

在我们正在处理的Delphi应用程序中,我们有一个相关对象的大结构。这些对象的某些属性具有在运行时计算的值,我正在寻找一种方法来缓存结果,以便进行更密集的计算。我使用的一种方法是在第一次计算时将值保存在私有成员中。下面是一个简短的例子:

unit Unit1;

interface

type
  TMyObject = class
  private
    FObject1, FObject2: TMyOtherObject;
    FMyCalculatedValue: Integer;
      function GetMyCalculatedValue: Integer;
  public
    property MyCalculatedValue: Integer read GetMyCalculatedValue;
  end;

implementation

  function TMyObject.GetMyCalculatedValue: Integer;
  begin
    if FMyCalculatedValue = 0 then
    begin
      FMyCalculatedValue :=
        FObject1.OtherCalculatedValue + // This is also calculated
        FObject2.OtherValue;
    end;

    Result := FMyCalculatedValue;
  end;

end.
用于计算的对象更改和缓存的值应该重置并重新计算,这种情况并不少见。到目前为止,我们通过使用观察者模式解决了这个问题:对象实现OnChange事件,以便其他人可以订阅、在更改和重置缓存值时得到通知。这种方法可行,但也有一些缺点:

  • 管理订阅需要大量内存
  • 当缓存的值依赖于许多对象(例如列表)时,它的伸缩性不好
  • 依赖关系不是很具体(即使缓存值仅依赖于一个属性,当其他属性更改时也会重置)
  • 管理订阅会影响总体性能,并且很难维护(对象被删除、移动等)
  • 不清楚如何根据其他计算值处理计算

最后一个问题是:您能推荐其他实现缓存计算值的方法吗?

如果您想避免观察者模式,您可以尝试使用散列方法

这样做的想法是对参数进行“散列”,并检查其是否与保存状态的“散列”匹配。如果没有,则重新计算(从而将新哈希保存为密钥)

我知道我让它听起来像是我刚刚考虑过的,但事实上它是由知名软件使用的

例如,(Makefile alternative)检查目标是否需要重新构建,最好是使用时间戳方法


我们已经使用SCON一年多了,我们从未检测到任何未重建的目标问题,所以它们的哈希工作得很好

您可以存储所需的外部对象值的本地副本。然后,访问例程将本地副本与外部值进行比较,并且仅对更改进行重新计算

访问外部对象属性同样会强制对这些属性进行可能的重新评估,因此系统应自动保持自身最新,但仅在需要时重新计算。我不知道您是否需要采取措施来避免循环依赖

这会增加每个对象所需的空间量,但会删除观察者模式。它还会将所有计算推迟到需要时,而不是在每次源参数更改时执行计算。我希望这与您的系统相关

unit Unit1;

interface

type
  TMyObject = class
  private
    FObject1, FObject2: TMyOtherObject;
    FObject1Val, FObject2Val: Integer;
    FMyCalculatedValue: Integer;
      function GetMyCalculatedValue: Integer;
  public
    property MyCalculatedValue: Integer read GetMyCalculatedValue;
  end;

implementation

  function TMyObject.GetMyCalculatedValue: Integer;
  begin
    if (FObject1.OtherCalculatedValue <> FObjectVal1)
    or (FObject2.OtherValue <> FObjectVal2) then
    begin
      FMyCalculatedValue :=
        FObject1.OtherCalculatedValue + // This is also calculated
        FObject2.OtherValue;
      FObjectVal1 := FObject1.OtherCalculatedValue;
      FObjectVal2 := Object2.OtherValue;
    end;

    Result := FMyCalculatedValue;
  end;

end.

在我的工作中,我使用Delphi的粗体,它可以管理无限的复杂的缓存值结构,这些缓存值相互依赖。通常每个变量只包含问题的一小部分。在这个框架中,它被称为派生属性。派生因为该值不保存在数据库中,所以它只依赖于数据库中的其他派生属性或持久属性

此类属性背后的代码是作为过程或模型中的OCL(对象约束语言)在Delphi中编写的。如果您将其作为Delphi代码编写,则必须订阅依赖的变量。因此,如果属性C依赖于A和B,那么每当A或B更改recalc的代码时,在读取C时会自动调用C。因此,第一次读取C时,A和B也会被读取(可能是从数据库中读取)。只要A和B不改变,就可以读取C并获得非常快的性能。对于复杂的计算,这可以节省相当多的CPU时间

缺点和坏消息是,政府不再支持Bold,你也不能买它。如果你问足够多的人,我想你可以得到,但我不知道你可以从哪里下载。大约在2005-2006年,它可以从Borland免费下载,但现在不再是了。 它还没有为D2009做好准备,因为有人必须将其移植到Unicode

另一个选项是使用来自的.net。ECO是Visual Studio中的一个插件。这是一个受支持的框架,与Delphi的Bold具有相同的想法和作者。许多方面也得到了改进,例如GUI组件使用了数据绑定。Bold和ECO都使用模型作为具有类、属性和链接的中心点。这些可以保存在数据库或xml文件中。在ECO的免费版本中,模型最多可以有12个类,但我记得没有其他限制

Bold和ECO包含的不仅仅是派生属性,它们使您的工作效率更高,并允许您思考问题,而不是数据库的技术细节,或者在您的情况下如何缓存值。欢迎您提出更多关于这些框架的问题

编辑:
实际上有一个德尔福黑体版D7的下载,相当老了。。。我知道D2005,ad D2006有更新。

即使标记为“delphi”,我也很想知道是否开发了特定的模式。我添加了delphi标记,以便将建议限制为静态类型,不是垃圾收集语言。为了安全起见,我还将在执行计算之前验证是否分配了fObject1和fObject2。@skamradt:同意。我假设这个问题忽略了输入验证/错误检测,以保持示例代码的简单。只需确保计算哈希(或您选择的任何方法)比重新计算(明显)快。是的,我没有指出这一点,因为它听起来很明显,但与优化一样。。。你真的必须测量。一般来说,模型驱动的框架,特别是“Bold for Delphi”听起来非常有趣。非常感谢。事实上,我在我的一个硬盘上发现了D2006的粗体(我认为这是最新的公开版本),所以如果你是int