My programming skill has gotten rusty, so I would like to elicit constructive criticism that can make me write code better. I know the standard design is to use templates, and even obtain the hash function, allocator, etc through it, but I wanted to experiment with patterns, so I'm pretty sure my design here blows. but I'm trying to use the strategy pattern to make a customizable hash table interface, just to reacquaint myself with C++.
How do I design this better (without using all the template parameters, for specifying hash function, etc)? If not the strategy pattern, what pattern would fit better?
//The generic map interface
template <typename K, typename V>
class Map
{
private:
//Make a reference class so we can enable [] operation
class reference
{
public:
operator V const () { return map_.Find(key_); }
reference& operator=(const V& val) { map_.Add(key_, val); return *this; }
reference& operator=(const reference& ref) { *this = (V&) ref; return *this; }
private:
reference (Map& map, const K key) : map_(map), key_(key) {}
Map& map_;
K key_;
friend class Map;
};
public:
Map() : hash_(NULL), ds_(NULL), size_(0) { }
void SetHashStrategy(int hash_type = HashType::SIMPLE_HASH);
void SetCollisionStrategy(int collision_method = CollisionType::CHAINING);
void SetDataStructureStrategy(int data_structure_types = DSType::DYNAMIC_MAP);
virtual ~Map()
{
Empty();
delete hash_;
delete ds_;
}
//Interface functions
void Add(K key,V value) { ++size_; ds_->Add(key, value); }
void Remove(K key) { --size_; ds_->Remove(key); }
V& Find(K key) { return ds_->Find(key); }
size_t Size() { return size_; }
void Empty() { size_ = 0; ds_->Empty(); }
//Square bracket access
reference operator[] (const K& key) { return (reference(*this, key)); }
//printing
friend std::ostream& operator<< (std::ostream& o, const V& v) { return o << v; }
private:
HashType* hash_; //is an ADT
DataStructureType<K,V>* ds_; //this is also an ADT
size_t size_;
};
And then, choose the hash object like this:
template <class K, class V>
void Map<K,V>::SetHashStrategy(int hash_type)
{
if(hash_ != NULL)
{
delete hash_;
}
if(hash_type == HashType::SIMPLE_HASH)
{
hash_ = new SimpleHash;
}
else if(hash_type == HashType::MD5_HASH)
{
hash_ = new MD5Hash;
}
}
And choose the data structure like this:
template <class K, class V>
void Map<K,V>::SetDataStructureStrategy(int ds_type)
{
if(ds_ != NULL)
{
delete ds_;
}
if(ds_type == DSType::DYNAMIC_MAP)
{
ds_ = new DynamicMap<K,V>;
}
else if(ds_type == DSType::ARRAY_MAP)
{
ds_ = new ArrayMap<K,V>;
}
}