我使用 C++ 中的模板化类实现了多模式。
#ifndef MULTITON_H
#define MULTITON_H
#include <map>
template <typename Key, typename T> class Multiton
{
public:
static void destroy()
{
for (typename std::map<Key, T*>::iterator it = instances.begin(); it != instances.end(); ++it) {
delete (*it).second;
}
}
static T& getRef(const Key& key)
{
typename std::map<Key, T*>::iterator it = instances.find(key);
if (it != instances.end()) {
return *(T*)(it->second);
}
T* instance = new T;
instances[key] = instance;
return *instance;
}
static T* getPtr(const Key& key)
{
typename std::map<Key, T*>::iterator it = instances.find(key);
if (it != instances.end()) {
return (T*)(it->second);
}
T* instance = new T;
instances[key] = instance;
return instance;
}
protected:
Multiton() {}
virtual ~Multiton() {}
private:
Multiton(const Multiton&) {}
Multiton& operator= (const Multiton&) { return *this; }
static std::map<Key, T*> instances;
};
template <typename Key, typename T> std::map<Key, T*> Multiton<Key, T>::instances;
#endif
用法:
class Foo : public Multiton<std::string, Foo> {};
Foo& foo1 = Foo::getRef("foobar");
Foo* foo2 = Foo::getPtr("foobar");
Foo::destroy();
有什么改进建议吗?
最佳答案
1) 个人偏好,但我会颠倒模板参数的顺序并将 Key 默认为 std::string (如果这是您最常使用的)
template <typename Key, typename T> class Multiton { ... }
然后你可以这样做:
class Foo : public Multiton<Foo> {};
class Bar : public Multiton<Bar,int> {};
我觉得哪个更好。
2) 此外,如果您从不将指针/引用传递给 Multitron(这不会违反模式),您就不需要在类中使用虚拟析构函数。
3) 如果你为你的 T*s 使用了一个更智能的容器,你就可以避免调用 Foo::destroy()。
类似于 std::map<Key,boost::shared_ptr<T> >
当静态实例被销毁时,将销毁所有对象。 (尽管如果你关心破坏顺序,那么你需要一些更聪明的东西——你可以从现有的单例解决方案中改编一些东西,比如凤凰单例等)
4) 您可以将迭代器更改为 const_iterators。
5) destroy 应该清除映射以防止在调用 destroy 后意外访问无效内存。或者,如果您想防止这种情况发生,您应该抛出异常。
Foo* foo2 = Foo::getPtr("foobar");
Foo::destroy();
Foo::getPtr("foobar")->doSomething(); // BANG
6) 如果你不使用多态 T 那么你可以使用 std::map 并且你的代码看起来像这样......
template <typename Key, typename T> class Multiton
{
public:
//Can probably get rid of this guy as maps destructor will do the right thing
static void destroy()
{
instances.clear();
}
static T& getRef(const Key& key)
{
return instances[key];
}
static T* getPtr(const Key& key)
{
return &instances[key];
}
protected:
Multiton() {}
virtual ~Multiton() {}
private:
Multiton(const Multiton&) {}
Multiton& operator= (const Multiton&) { return *this; }
static std::map<Key, T> instances;
};
目前我能想到的就这些了。</p>
关于多模式的 C++ 模板类实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2346091/