实现“脏”标志功能的不同方法

时间:2009-02-16 16:27:37

标签: design-patterns

几乎每个程序员一生都做过一次:如果变量的值发生变化,设置一些标志。总是有很多属性,如果发生了变化,你想跟踪

  1. in any property
  2. 在特定属性中
  3. 或某些属性
  4. 我对以上情况实现“脏标志”功能的不同方式感兴趣,除了在每次属性更改时更新标准对象范围的脏标志。必须有比在每个setter中放置“dirty = true”更好的东西:它看起来很丑陋而且是一项繁琐的工作。

8 个答案:

答案 0 :(得分:24)

对于我的DAO,我保留了从数据库中检索到的原始值的副本。当我发送它进行更新时,我只是将原始值与当前值进行比较。它的处理成本稍高,但它比每个属性都有一个脏标志要好得多。

编辑以进一步证明没有脏标志:如果属性返回其原始值,则无法反映出来,脏标志会继续变脏,因为原始值已丢失。

答案 1 :(得分:10)

我曾经有一个基本的Entity类,提供了Dirty / Removed Logic。

编写实体子类时,可以执行以下操作:

public string Name
{
    get { return name; }
    set { setValue("Name", value); }
}

这种方法很好,但有“丑陋的字符串”疾病......

今天你可以使用Lambda表达式来排除字符串:

set {setValue(x => x.Name, value);}

或者,我认为这是最好的解决方案,您可以使用AOP

https://www.postsharp.net/

这样,您可以按属性定义操作。您创建一个属性并指定当用户更改关联属性时,该实体变脏。

此外,您可以在您的类(基本实体)中保留一个属性列表,它将记住更改的属性,并从您的AOP代码访问该列表。

答案 2 :(得分:8)

我创建了一个名为DirtyValue<T>的类,它有一个原始值和一个当前值。首次使用时,它会设置原始值和当前值。连续调用仅设置当前值。

你可以通过比较两者来判断它是否已经改变了,只有一个名为IsDirty()的readonly bool属性。使用这种技术,您也可以访问原始值。

答案 3 :(得分:6)

如果您设置“脏”标志,则意识到您保持状态。在某些时候,您需要根据该状态采取行动,否则您不需要保留该标志。那么问题就变成了:是否还有另一种触发所需行动的方法?发送某种消息?谁消耗“脏”状态并采取行动,是否有更清晰的通知接口?

答案 4 :(得分:5)

在某些具有数据编写器任务和独立读者任务的情况下,我给每个任务一个updateCount变量。生成器在写入时递增其计数。每当读者醒来并发现其计数小于生产者的计数时,它会使用当前值进行更新。您需要对计数器溢出进行一些特殊处理,但实现起来非常简单。

我在模拟中成功地使用了这种技术 - 生产者是物理循环而读者是3d显示器。

答案 5 :(得分:4)

我会在每个setter中放置changed(),即调用私有方法而不是仅仅更改标志。然后,该方法可以设置标志或进行任何需要的处理,例如,它也可以通知任何观察员。

答案 6 :(得分:2)

显式dirty=true方法的一个有趣的替代方法,虽然在大多数情况下可能是过度杀戮,而且通常不适用,但是使用保护页面。将内存页面设置为只读(例如,在Windows上使用VirtualProtect())并在程序尝试写入页面时捕获信号/异常。记录页面已被修改,然后将页面的保护标志更改为可写并继续执行。

这是操作系统通常采用的技术,用于确定页面是否需要在从RAM中逐出之前写入交换文件。

答案 7 :(得分:-1)

您可能希望查看覆盖域对象的gethashcode和equals方法,并按对象键将原始哈希码存储在哈希表中。然后创建一个进程,该进程接受一个对象,在哈希表中找到它的键并比较哈希值。

  • 如果哈希相同,则无变化。 (不要发送到存储库或数据库)
  • 如果哈希不同,则对象有变化。 (更新)
  • 如果找不到密钥,则对象是新的。 (插入)
  • 不确定如何确定是否需要删除对象,而不是根据请求删除进程而不使用哈希码跟踪。

我没有尝试过这个,哈希表可能不是跟踪对象键/哈希值的最佳方法。它只会通过跟踪哈希码和密钥来保存mem。我不是百分百肯定,但我认为一些orm可能会在他们的数据上下文/跟踪对象中使用此方法。