#pragma once #include #include #include "ActionAddItem.h" #include "ItemEraser.h" #include "DrawOperator/Util.h" #include "Util.h" /** * 对象代理类,用于获取和设置对象属性 */ class ObjectProxy { public: virtual ~ObjectProxy() = default; /** * 获取属性,为了通用,我们全部使用字符串 * * \param name 属性名称 * \return 属性值 */ virtual CString GetProperty(const CString& name) const = 0; /** * 设置属性 * * \param name 属性名称 * \param value 属性值 */ virtual void SetProperty(const CString& name, const CString& value) = 0; }; /** * 橡皮擦代理对象 */ class CItemEraserProxy : public ObjectProxy { public: CItemEraserProxy(CItemEraser* eraser) : m_eraser(eraser) { assert(m_eraser != nullptr); } CString GetProperty(const CString& name) const override { if (name == EraserMode) { return GetEraserMode(); } else if (name == EraserRadius) { return GetEraserRadius(); } else { return ""; } } void SetProperty(const CString& name, const CString& value) override { if (name == EraserMode) { SetEraserMode(value); } else if (name == EraserRadius) { SetEraserRadius(value); } } private: CString GetEraserMode() const { switch (m_eraser->GetEraserMode()) { case EraserMode::Normal: return Normal; break; case EraserMode::Segments: return Segments; break; case EraserMode::Nodes: return Nodes; break; case EraserMode::Relink: return Relink; break; default: return ""; } } void SetEraserMode(const CString& mode) { if (mode == Normal) { m_eraser->SetEraserMode(EraserMode::Normal); } else if (mode == Segments) { m_eraser->SetEraserMode(EraserMode::Segments); } else if (mode == Nodes) { m_eraser->SetEraserMode(EraserMode::Nodes); } else if (mode == Relink) { m_eraser->SetEraserMode(EraserMode::Relink); } } CString GetEraserRadius() const { return ToCString(m_eraser->GetEraserRadius()); } void SetEraserRadius(const CString& value) { int radius = _ttoi(value); m_eraser->SetEraserRadius(radius); } CItemEraser* m_eraser; const LPCTSTR EraserMode = _T("EraserMode"); const LPCTSTR EraserRadius = _T("EraserRadius"); const LPCTSTR Normal = _T("Normal"); const LPCTSTR Segments = _T("Segments"); const LPCTSTR Nodes =_T("Nodes"); const LPCTSTR Relink =_T("Relink"); }; /** * @class ObjectProxyFactory * @brief 代理对象工厂类,用于根据类型名称动态创建对应的代理对象。 * * 此工厂类维护一个构造函数映射表,可以注册和注销特定类型的构造器。 * 客户端通过名称和构造参数创建相应的代理对象,支持运行时多态性和灵活的对象构建。 */ class ObjectProxyFactory { public: /** * @brief 构造函数,初始化并注册默认的代理构造器。 * * 使用 typeid 注册类型名称,避免手动拼写错误; * 提供默认的 CItemEraser 类型代理构造器。 */ ObjectProxyFactory() { // 我们在注册时使用 typeid 以免后缀名拼写错误,但是我们注册接口不这么做,对外提供灵活性 RegisterConstructor(typeid(CItemEraser).name()); } /** * @brief 注册一个代理对象的构造函数。 * * @tparam Proxy 要创建的代理类类型,需继承自 ObjectProxy。 * @tparam Arg 构造 Proxy 所需的参数类型。 * @param name 用于标识该构造函数的名称(一般为目标类型的名称)。 */ template void RegisterConstructor(const CString& name) { auto constructor = [](std::any arg) -> std::unique_ptr { return std::make_unique(std::any_cast(arg)); }; m_constructors[name] = constructor; } /** * @brief 注销一个已注册的构造函数。 * * @param name 要注销的构造器名称。 */ void UnregisterConstructor(const CString& name) { auto it = m_constructors.find(name); if (it != m_constructors.end()) { m_constructors.erase(it); } } /** * @brief 根据名称和参数创建对应的代理对象。 * * @param name 目标类型的名称(必须已注册构造器)。 * @param arg 构造该对象所需的参数(需与注册时一致)。 * @return std::unique_ptr 成功则返回代理对象,失败返回 nullptr。 */ std::unique_ptr Create(const CString& name, std::any arg) const { auto it = m_constructors.find(name); if (it != m_constructors.end()) { return it->second(arg); } return nullptr; } private: using constructor = std::function (std::any)>; std::unordered_map m_constructors; };