C++ 通知一个类另一个类';变化

C++ 通知一个类另一个类';变化,c++,design-patterns,C++,Design Patterns,拥有容器、项目和属性,当项目中的属性发生变化时,应通知容器 容器是项目的所有者,需要信息根据其属性对其进行正确管理 我已经想到了两种选择: 观察者模式 代理对象 在我看来,观察者模式对于这项任务来说似乎太重了。代理对象可以很好地工作,但是在这种情况下,我会违反DRY原则,因为我必须将代理调用转发到实际对象 要求对用户隐藏详细信息。要求不需要调用某些update\u item()函数或类似函数,即将通知容器的责任交给用户,这可能会导致使用问题。在这种简单的情况下,我看不到使用观察者的理由。由于一个

拥有
容器
项目
属性
,当项目中的属性发生变化时,应通知容器

容器是项目的所有者,需要信息根据其属性对其进行正确管理

我已经想到了两种选择:

  • 观察者模式
  • 代理对象
  • 在我看来,观察者模式对于这项任务来说似乎太重了。代理对象可以很好地工作,但是在这种情况下,我会违反DRY原则,因为我必须将代理调用转发到实际对象


    要求对用户隐藏详细信息。要求不需要调用某些
    update\u item()
    函数或类似函数,即将通知容器的责任交给用户,这可能会导致使用问题。

    在这种简单的情况下,我看不到使用
    观察者的理由。由于一个
    项目
    一次只能在一个容器中,我只想给
    项目
    一个指向其所在容器的引用或指针

    项的
    属性
    更改时,可以通过该指针通知它的
    容器

    Observer
    模式在需要通知多个对象的情况下非常有用

    编辑

    使用界面和极其干净的设计来做每一件简单的事情也可能会伤害你。我认为Python的zen的引用很好地解释了我的意思:

    Special cases aren't special enough to break the rules. //make Interfaces
    Although practicality beats purity. //but not everywhere
    

    因此,您应该在纯度和实用性之间保持平衡

    您应该使用最容易理解和维护的模式,并且需要最少的专门组件发明。在我工作的环境(objective-C)中,observer模式非常简单。当您的通知要求发生变化时,它还提供了灵活性

    Andrew的答案是事件更简单-对象之间的直接通信不需要发明代理或通知处理的开销。但是如果你将来需要的话,它的灵活性就比较小了


    我不知道“太重”是什么意思。也许你可以解释一下。

    正如前面所提到的,观察者在这里是非常过分的,但解决方案非常简单。你只需要“泡泡”活动

    • 当属性发生更改时,它会通知其父项
    • 当项目发生更改时(属性更改的副作用,或项目更完整的部分),它会通知其容器/父项)
    • 当一个容器收到通知时,那么,您就完成了。如果容器可以嵌套,那么我猜它可以在必要时向其父容器引发事件

    我认为这种方法的问题是
    项目
    依赖于
    容器
    ,而
    容器
    依赖于
    项目
    。这不是C++的问题,但它意味着一个设计缺陷。一般来说,我倾向于将事情隔离。@Tank:如果您愿意,您可以通过一些
    容器接口
    项目接口
    或类似的方式进行通信。它与为观察者模式创建接口没有区别。但尽量不要把简单的事情复杂化)这是阅读像《干净的代码》等书籍的结果当
    Item
    依赖于
    Container
    时,我会立即意识到在单元测试中,老实说,必须在那里处理
    Container
    会让人感到奇怪。接口的想法对我来说很好,因为它放松了依赖关系。明白了,谢谢。我还是有点犹豫不决,因为我害怕那些“啊,不管怎样,让我们这样做,这样它就可以工作”的决定,如果你知道我的意思的话。这有点有趣,复杂,而且比这些小东西更容易设计更大的东西与Andrew的建议类似的问题是:它将向上添加层次依赖关系。这就像一个轮子必须了解汽车一样@坦克,但在某种意义上,车轮不需要知道汽车。它只是转动。这本身就是一件大事。汽车是否能听到车轮转动的声音无关紧要。我们只提供信息传播的机制。:)这是真的,但是车轮也可以在没有汽车的情况下生存,
    Item
    无法在没有容器的情况下生存,除非您允许没有父对象,但通常情况并非如此。好了,别再胡闹了“太重”是指您实际描述的内容:观察者模式的开销。对于仅在内部发生的事情(即,用户永远不会订阅对象)。我能想到的最简单的解决方案是代理,但这很烦人,因为它会复制代码。