与上一篇《[笔记]C++代码演示Singleton单类实例》不同,本篇演示的是利用 STL 里的 map 和 list 容器,根据索引 key 的不同,返回不同的单实例类,调用举例如下:
MySingletonMap* MySM1 = SingletonMap<MySingletonMap>::GetInstance(1);
UML类图如下:
由上图易知,SingletonMap 是模板类,MySingletonMap 继承自 SingletonMap,具体代码如下:
#include <iostream> #include <map> #include <list> using namespace std; // 使用 map 存放单类实例的基类 template <class T, typename K = int> class SingletonMap{ public: // 先从 map 中根据 key 查找实例,如果没有就创建实例 static T* GetInstance(K key){ // 根据 key 查找实例 typename map<K, T*>::iterator iter = GetMap().find(key); // 如果找到,就返回 if (iter != GetMap().end()){ return iter->second; } // 否则创建新的实例 // 此处会进到构造函数 SingletonMap(K key) 里面,将实例插入 map 和 list 中 return new T(key); } // 返回实例列表 static list<T*>& GetAllInstances(){ static list<T*> List; return List; } // 删除全部实例 static void DeleteAllInstances() { list<T*>& List = GetAllInstances(); list<T*>::iterator v; // 遍历 list 内的实例 for(v = List.begin(); v != List.end();){ cout << "Delete Instance " << ((T*)(*v))->getKey() << endl; delete *v; // 删除该项对应的实例 v = List.erase(v); // 从 list 中删除该项 } } // 获得 key K getKey() const { return m_Key; } protected: SingletonMap(K key): m_Key(key){ pair<const K, T*> Elem(key, (T*)this); // 创建 pair GetMap().insert(Elem); // 将 pair 插入 map GetAllInstances().push_back((T*)this); // 将自身插入 list } private: static map<K, T*>& GetMap(){ static map<K, T*> Map; // 此处生成静态 map return Map; } K m_Key; // key }; // 继承自 SingletonMap 的子类 class MySingletonMap: public SingletonMap<MySingletonMap>{ private: friend class SingletonMap<MySingletonMap>; // 将 SingletonMap 设为 friend class MySingletonMap(int key): SingletonMap<MySingletonMap>(key){} virtual ~MySingletonMap(){} }; int main(int argc, char* argv[]) { MySingletonMap* MySM1 = SingletonMap<MySingletonMap>::GetInstance(1); // 创建新实例 cout << "Number of instances = " << MySingletonMap::GetAllInstances().size() << endl; // 返回1 MySingletonMap* MySM2 = SingletonMap<MySingletonMap>::GetInstance(2); // 创建新实例 cout << "Number of instances = " << MySingletonMap::GetAllInstances().size() << endl; // 返回2 MySingletonMap* MySM3 = SingletonMap<MySingletonMap>::GetInstance(2); // 得到实例 MySM2 cout << "Number of instances = " << MySingletonMap::GetAllInstances().size() << endl; // 返回2 if (MySM2 == MySM3) { cout << "MySM2 == MySM3" << endl; // 因为二者相等,所以打印 MySM2 == MySM3 } else { cout << "MySM2 != MySM3" << endl; } MySingletonMap::DeleteAllInstances(); // 删除全部实例 getchar(); return 0; }
VC2010编译运行,结果为:
Number of instances = 1 Number of instances = 2 Number of instances = 2 MySM2 == MySM3 Delete Instance 1 Delete Instance 2
可见无需显式实例化,即可通过不同的索引得到不同的类单实例,这是用到了内含的 map。
如果需要遍历全部的实例,也可以利用内含的 list 进行迭代。
需要注意的是,上面代码并没有对由此获得的每个单实例的析构做处理,这一步就留给有兴趣者吧。
好吧,代码已经更新,提供了对全部实例的析构函数 DeleteAllInstances()。