我处于需要在多态对象树的多个实例之间共享数据的情况,但是我再次需要共享数据" per-tree"所以在基类中使用静态类成员实际上并不是一种选择。
我不想过度负担"每个实例都有指向共享数据的额外成员指针,因此我当前的方法(考虑到我使用树)是将共享数据作为树根节点的成员,并且每次访问共享数据都要经过一系列间接,具体取决于特定节点的深度"树全局"访问数据。
由于有些情况下共享数据非常频繁(每秒数百万......至少是那些预期的内容),我想知道是否有一些设计模式可以帮助我避免间接到到达根节点,同时仍然没有将额外的膨胀引入对象的足迹。
虽然可以"缓存"根节点指针作为本地,例如用于访问共享数据的紧密循环,在许多情况下,功能将沿树节点级联,甚至在过程中切换树,因此缓存根节点指针仅适用于狭窄的上下文。
答案 0 :(得分:0)
与树节点交互的所有方法都将第一个参数作为指向根的指针。
flyweight包装器类可以隐藏此实现细节,您可以通过opaque类访问树节点,其中包含一个真实的树节点指针以及一个用于根目录的poimter。如果你要求孩子,它会返回另一个轻量级。
现在你的树缺少额外的指针,但接口类有额外的指针。
如果您的树节点是不可变的(逻辑上),您甚至可以复制它们的状态以减少间接成本。
template<class Data>
struct internal_tree {
Data d;
std::unique_ptr<internal_tree> left;
std::unique_ptr<internal_tree> right;
};
template<class Data>
struct flyweight_tree {
private:
internal_tree* internal = nullptr;
internal_tree* root = internal;
flyweight_tree(internal_tree* t, internal_tree* r):internal(t),root(r) {}
public:
flyweight_tree() {}
flyweight_tree(internal_tree* r):internal(r) {}
flyweight_tree left() const { return { internal->left.get(), root }; }
flyweight_tree right() const { return { internal->right.get(), root }; }
};
现在我们的实际internal_tree
数据结构不存储指向root的指针。使用它的代码通过flyweight_tree
访问它,它存储指向root的指针,但指针到root只存储在访问点,永远不会长期存储。
如果你想要一个parent
,你甚至可以将它实现为一个轻量级,其中flyweight_tree
存储std::vector
指针到父级(而不是root
)。这会在树节点中保存另一堆内存(没有指向父节点的指针,但是使用它的每个人都可以获得父节点,因为它们通过flyweight_tree
使用它。)
我们可以在internal_tree
中实现大部分工作,它将flyweight_tree
存储的信息作为参数,或者我们可以在flyweight_tree
中实现大多数树逻辑,将internal_tree
留作紧凑的“长期存储”结构。
答案 1 :(得分:0)
我能想到的可能性是: