Multiton模式的C ++模板化类实现 [英] C++ templated class implementation of the multiton pattern

查看:56
本文介绍了Multiton模式的C ++模板化类实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用C ++中的模板化类实现了multiton模式.

I implemented the multiton pattern using a templated class in 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(如果要使用的话)大多数)

1) Personal preference, but I'd reverse the order of the template parameters and default the Key to std::string (if that's what you'll use most)

template <typename Key, typename T> class Multiton { ... }

然后您可以执行以下操作:

Then you can do this:

class Foo : public Multiton<Foo> {};
class Bar : public Multiton<Bar,int> {};

我认为更好.

2)另外,如果您从不将指针/引用传递给Multitron(这不会违反模式),则在类中不需要虚拟析构函数.

2) Also if you're never passing pointers/references to Multitron (which wouldn't kind of violate the patter) you shouldn't need a virtual destructor in the class.

3)如果为T *使用了更智能的容器,则可以避免调用Foo :: destroy().类似于 std :: map< Key,boost :: shared_ptr< T>> 会在销毁静态实例时销毁所有对象.(尽管如果您关心销毁的顺序,那么您将需要一些更聪明的方法-您可以从现有的单例解决方案(例如凤凰式单例)中适应某些方法)

3) If you used a smarter container for your T*s you could avoid having to call Foo::destroy(). Something like std::map<Key,boost::shared_ptr<T> > would destroy all the objects when the static instance was destroyed. (Although if you cared about order of destruction, then you'd need something cleverer - you could adapt somethign from existing singleton solutions such as phoenix singletons etc)

4)您可以将迭代器更改为const_iterators.

4) You could change your iterators to const_iterators.

5)destroy可能应该清除映射,以防止在调用destroy之后意外访问无效内存.或者,如果您想防止这种情况,则应该抛出异常.

5) destroy should probably clear the map to prevent accidental access of invalid memory after calling destroy. Or if you want to protect against this you should throw an exception.

Foo* foo2 = Foo::getPtr("foobar");
Foo::destroy();
Foo::getPtr("foobar")->doSomething(); // BANG

6)如果您不使用多态T,则可以使用std :: map,您的代码将如下所示……

6) If you're not using polymorphic T then you could use a std::map and your code would look like this...

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;
};

这就是我现在能想到的一切.

That's about all I can think of for now.

这篇关于Multiton模式的C ++模板化类实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆