Pattern InstancePool
От: BULAT GAIFULLIN Россия  
Дата: 22.07.10 18:36
Оценка:
Хочу предложить вашему внимание паттерн проектирования InstanceManager;
Данный класс позволяет использовать только один экземпляр любого класса в программе не прибегая к помощи синглтонов:

//////////////////////////////////////////////////////////////////////////
// Therading model class example
struct SingleThread
{
  void Lock() {}
  void Unlock() {}
};

template <class T>
struct MutexLocker
{
  MutexLocker(T& m) : MyMutex(&m) { MyMutex->Lock(); };
  ~MutexLocker() { MyMutex->Unlock(); }
private:
  T* MyMutex;
};
//////////////////////////////////////////////////////////////////////////
/// class Instance pool

template<class ThreadingModel = SingleThread>
class InstanceManager
{
  class InstanceBase
  {
  public:
    virtual ~InstanceBase() {}
  };

  template <class T>
  class Instance : public T, public InstanceBase
  {
  };
public:
  ~InstanceManager()
  {
    while (!ObjectPool.empty())
    {
      delete ObjectPool.begin()->second;
      ObjectPool.erase(ObjectPool.begin());
    }
  }
  template <class T>
  T* GetInstance(const T* t = 0)
  {
    const Loki::TypeInfo id(typeid(t));
    ObjectPoolMap::iterator o = ObjectPool.find(id);
    if (o == ObjectPool.end())
    {
      MutexLocker<ThreadingModel> locker(InsertMutex);
      o = ObjectPool.find(id);
      if (o == ObjectPool.end())
      {
        o = ObjectPool.insert(ObjectPoolMap::value_type(id, new Instance<T>())).first;
      }
    }
    return static_cast<T*>(static_cast<Instance<T>* >(o->second));
  }
private:
  ThreadingModel InsertMutex;
  typedef std::map<Loki::TypeInfo, InstanceBase*> ObjectPoolMap;
  ObjectPoolMap ObjectPool;
};


пример использования:

class TestClass
{
public:
  TestClass() { std::cout<< "TestClass" << std::endl;  }
  virtual ~TestClass() { std::cout<< "~TestClass" << std::endl;  }
  void Print() { std::cout<< "TestClass::Print" << std::endl;  }
};

class TestClass2
{
public:
  TestClass2() { std::cout<< "TestClass2" << std::endl;  }
  virtual ~TestClass2() { std::cout<< "~TestClass2" << std::endl;  }
  void Print() { std::cout<< "TestClass2::Print" << std::endl;  }
};

void TestProgramm()
{
  InstanceManager<SingleThreading> manager;
  manager.GetInstance<TestClass>()->Print();
  manager.GetInstance<TestClass2>()->Print();
  manager.GetInstance<TestClass>()->Print();
  manager.GetInstance<TestClass2>()->Print();
  return 0;
}





класс TypeInfo, код взят из библиотеки Loki

namespace Loki
{
  class TypeInfo
  {
  public:
    // Constructors
    TypeInfo(); // needed for containers
    TypeInfo(const std::type_info&); // non-explicit

    // Access for the wrapped std::type_info
    const std::type_info& Get() const;
    // Compatibility functions
    bool before(const TypeInfo& rhs) const;
    const char* name() const;

  private:
    const std::type_info* pInfo_;
  };

  // Implementation

  inline TypeInfo::TypeInfo()
  {
    class Nil {};
    pInfo_ = &typeid(Nil);
    assert(pInfo_);
  }

  inline TypeInfo::TypeInfo(const std::type_info& ti)
  : pInfo_(&ti)
  { assert(pInfo_); }

  inline bool TypeInfo::before(const TypeInfo& rhs) const
  {
    assert(pInfo_);
    // type_info::before return type is int in some VC libraries 
    return pInfo_->before(*rhs.pInfo_) != 0;
  }

  inline const std::type_info& TypeInfo::Get() const
  {
    assert(pInfo_);
    return *pInfo_;
  }

  inline const char* TypeInfo::name() const
  {
    assert(pInfo_);
    return pInfo_->name();
  }

  // Comparison operators

  inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
  // type_info::operator== return type is int in some VC libraries
  { return (lhs.Get() == rhs.Get()) != 0; }

  inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
  { return lhs.before(rhs); }

  inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
  { return !(lhs == rhs); }    

  inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
  { return rhs < lhs; }

  inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
  { return !(lhs > rhs); }

  inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
  { return !(lhs < rhs); }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.