#include #include #include #include #include #include #include class INode; class ILink; class ILinkMixin; using NodePtr = std::shared_ptr; using LinkPtr = std::shared_ptr; using LinkMixinPtr = std::shared_ptr; class ILink { public: virtual ~ILink() = default; virtual LinkPtr getParent() const = 0; virtual void setParent(LinkPtr parent) = 0; virtual const std::vector& getChildren() const = 0; virtual void addChild(LinkPtr child) = 0; virtual void removeChild(LinkPtr child) = 0; virtual NodePtr getNode() const = 0; virtual std::mutex& getLock() = 0; virtual LinkMixinPtr getLinkMixin() const = 0; }; class ILinkMixin { public: virtual ~ILinkMixin() = default; virtual void linkChild(const NodePtr& child) = 0; virtual void unlinkParent() = 0; virtual void unlinkChild(const NodePtr& child) = 0; virtual LinkPtr getLink() const = 0; virtual NodePtr getNode() const = 0; }; class INode { public: virtual ~INode() = default; virtual LinkPtr getLink() const = 0; virtual LinkMixinPtr getLinkMixin() const = 0; }; class LeafLink : public ILink { public: explicit LeafLink(NodePtr node) : node_(std::move(node)) {} LinkPtr getParent() const override { return parent_; } void setParent(LinkPtr parent) override { parent_ = std::move(parent); } const std::vector& getChildren() const override { static std::vector empty; return empty; } void addChild(LinkPtr) override { throw std::logic_error("LeafLink cannot have children"); } void removeChild(LinkPtr) override {} NodePtr getNode() const override { return node_; } std::mutex& getLock() override { return lock_; } LinkMixinPtr getLinkMixin() const override { return node_->getLinkMixin(); } private: NodePtr node_; LinkPtr parent_; mutable std::mutex lock_; }; class OneToManyLink : public ILink { public: explicit OneToManyLink(NodePtr node) : node_(std::move(node)) {} LinkPtr getParent() const override { return parent_; } void setParent(LinkPtr parent) override { parent_ = std::move(parent); } const std::vector& getChildren() const override { return children_; } void addChild(LinkPtr child) override { children_.push_back(std::move(child)); } void removeChild(LinkPtr child) override { children_.erase(std::remove(children_.begin(), children_.end(), child), children_.end()); } NodePtr getNode() const override { return node_; } std::mutex& getLock() override { return lock_; } LinkMixinPtr getLinkMixin() const override { return node_->getLinkMixin(); } private: NodePtr node_; LinkPtr parent_; std::vector children_; mutable std::mutex lock_; }; class OneToOneLink : public ILink { public: explicit OneToOneLink(NodePtr node) : node_(std::move(node)) {} LinkPtr getParent() const override { return parent_; } void setParent(LinkPtr parent) override { parent_ = std::move(parent); } const std::vector& getChildren() const override { return singleChildVec_; } void addChild(LinkPtr child) override { if (!singleChildVec_.empty()) { throw std::logic_error("OneToOneLink already has a child"); } singleChildVec_.push_back(std::move(child)); } void removeChild(LinkPtr child) override { if (!singleChildVec_.empty() && singleChildVec_.front() == child) { singleChildVec_.clear(); } } NodePtr getNode() const override { return node_; } std::mutex& getLock() override { return lock_; } LinkMixinPtr getLinkMixin() const override { return node_->getLinkMixin(); } private: NodePtr node_; LinkPtr parent_; std::vector singleChildVec_; mutable std::mutex lock_; }; // Типизированная связь один ко многим template class TypedOneToManyLink : public OneToManyLink { public: explicit TypedOneToManyLink(NodePtr node) : OneToManyLink(std::move(node)) {} void addChild(LinkPtr child) override { NodePtr n = child->getNode(); if (!std::dynamic_pointer_cast(n)) { throw std::invalid_argument("TypedOneToManyLink: child is not of expected type"); } OneToManyLink::addChild(std::move(child)); } }; // Базовая реализация LinkMixin class BaseLinkMixin : public ILinkMixin { public: explicit BaseLinkMixin(NodePtr self) { link_ = std::make_shared(self); } void linkChild(const NodePtr& child) override { LinkPtr childLink = child->getLink(); childLink->setParent(link_); link_->addChild(childLink); } void unlinkParent() override { if (!link_ || !link_->getParent()) return; auto parent = link_->getParent(); parent->getLinkMixin()->unlinkChild(link_->getNode()); link_->setParent(nullptr); } void unlinkChild(const NodePtr& child) override { LinkPtr childLink = child->getLink(); link_->removeChild(childLink); childLink->setParent(nullptr); } LinkPtr getLink() const override { return link_; } NodePtr getNode() const override { return link_->getNode(); } protected: LinkPtr link_; }; // Ленивый LinkMixin с выбором стратегии по типу template class LazyLinkMixin : public ILinkMixin { public: explicit LazyLinkMixin(NodePtr self) { link_ = std::make_shared(self); } void linkChild(const NodePtr& child) override { ensureInitialized(child); LinkPtr childLink = child->getLink(); childLink->setParent(link_); link_->addChild(childLink); } void unlinkParent() override { if (!link_ || !link_->getParent()) return; auto parent = link_->getParent(); parent->getLinkMixin()->unlinkChild(link_->getNode()); link_->setParent(nullptr); if (link_->getChildren().empty()) { link_ = std::make_shared(link_->getNode()); } } void unlinkChild(const NodePtr& child) override { if (!link_) return; LinkPtr childLink = child->getLink(); link_->removeChild(childLink); childLink->setParent(nullptr); if (link_->getChildren().empty()) { link_ = std::make_shared(link_->getNode()); } } LinkPtr getLink() const override { return link_; } NodePtr getNode() const override { return link_->getNode(); } private: void ensureInitialized(const NodePtr& child) { if (link_ && !std::dynamic_pointer_cast(link_)) return; LinkPtr oldLink = link_; LinkPtr newLink; if (std::dynamic_pointer_cast(child)) { newLink = std::make_shared>(oldLink->getNode()); } else { newLink = std::make_shared(oldLink->getNode()); } newLink->setParent(oldLink->getParent()); link_ = newLink; } LinkPtr link_; }; // Пример узла class SimpleNode : public INode, public std::enable_shared_from_this { public: static std::shared_ptr create(std::string name) { struct EnableMakeShared : public SimpleNode { EnableMakeShared(std::string n) : SimpleNode(std::move(n)) {} }; auto ptr = std::make_shared(std::move(name)); ptr->initMixin(); return ptr; } const std::string& name() const { return name_; } LinkPtr getLink() const override { return mixin_->getLink(); } LinkMixinPtr getLinkMixin() const override { return mixin_; } void linkChild(const std::shared_ptr& child) { mixin_->linkChild(child); } void unlinkParent() { mixin_->unlinkParent(); } private: explicit SimpleNode(std::string name) : name_(std::move(name)) {} void initMixin() { mixin_ = std::make_shared>(shared_from_this()); } std::string name_; LinkMixinPtr mixin_; }; // Пример использования void printTree(const LinkPtr& link, int indent = 0) { for (int i = 0; i < indent; ++i) std::cout << " "; auto node = link->getNode(); auto simpleNode = std::dynamic_pointer_cast(node); if (simpleNode) { std::cout << simpleNode->name() << "\n"; } for (const auto& child : link->getChildren()) { printTree(child, indent + 1); } } int main() { auto root = SimpleNode::create("Root"); auto child1 = SimpleNode::create("Child1"); auto child2 = SimpleNode::create("Child2"); root->linkChild(child1); root->linkChild(child2); auto subchild = SimpleNode::create("SubChild"); child1->linkChild(subchild); printTree(root->getLink()); std::cout << "\nUnlinking Child2...\n"; child2->unlinkParent(); printTree(root->getLink()); return 0; }