所有与树节点交互的方法都将指向根的指针作为它们的第一个参数。
享元包装类可以隐藏此实现细节,您可以通过不透明类访问树节点,该类具有真正的树节点指针以及指向其中的根指针。如果您要求一个孩子,它会返回另一个蝇量级。
现在你的树缺少额外的指针,但接口类有额外的指针。
如果您的树节点是不可变的(逻辑上),您甚至可以复制它们的状态以降低间接成本。
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
数据结构不存储指向根的指针。使用它的代码通过 a 访问它flyweight_tree
,它存储指向根的指针,但指向根的指针仅存储在访问点,从不长期存储。
如果您想要 a parent
,您甚至可以将其实现为享元,其中flyweight_tree
存储std::vector
指向父级的指针(而不是root
)。这在你的树节点中节省了另一堆内存(没有指向父节点的指针,但是每个使用它的人都可以得到父节点,因为他们通过 使用它flyweight_tree
)。
我们可以在 中实现大部分工作internal_tree
,它将flyweight_tree
存储的信息作为参数,或者我们可以在其中实现大部分树逻辑flyweight_tree
并将其保留internal_tree
为紧凑的“长期存储”结构。