c++でStrategyパターンってこんな感じ? 紆余曲折の結果

algorithmのインターフェースを設定しているクラスにstatic関数がいてもいいのかとても悩みながら。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4     
  5 #include <iostream>
  6 #include <string>
  7 #include <map>
  8 #include <stdexcept>
  9 #include <exception>
 10 #include "openssl/md5.h" 
 11 #include "openssl/sha.h"
 12 
 13 typedef unsigned int u_int;
 14         
 15 using std::cout;
 16 using std::cerr;
 17 using std::endl;
 18 using std::string;
 19 using std::logic_error;
 20 
 21 struct HashPtn
 22 {   
 23     virtual string get_hash( const string s ) const = 0;
 24         
 25     // 定義だけするはずのクラスでこんなことしてよいのだろうか?
 26     static char *pt(unsigned char *md, int len)
 27     {   
 28         int i; 
 29         // マジックナンバー、どうしたものか。
 30         static char buf[80];
 31         
 32         for (i=0; i<len; i++)
 33             sprintf(&(buf[i*2]),"%02x",md[i]);
 34         return(buf);
 35     }
 36 
 37 };  
 38     
 39 struct MD5_hash : public HashPtn 
 40 {       
 41     virtual string get_hash ( const string s ) const 
 42     {
 43         unsigned char digest[MD5_DIGEST_LENGTH];
 44         MD5_CTX ctx;
 45 
 46         MD5_Init(&ctx);
 47         MD5_Update(&ctx, reinterpret_cast<const unsigned char *>(s.c_str()), s.length());
 48         MD5_Final(digest, &ctx);
 49 
 50         string ret = reinterpret_cast<char *>(HashPtn::pt(digest, MD5_DIGEST_LENGTH));
 51         return ret;
 52     }
 53 };
 54 
 55 
 56 struct SHA1_hash : public HashPtn 
 57 {
 58     virtual string get_hash ( const string s ) const 
 59     {
 60         unsigned char digest[SHA_DIGEST_LENGTH];
 61         SHA_CTX ctx;
 62 
 63         SHA1_Init(&ctx);
 64         SHA1_Update(&ctx, reinterpret_cast<const unsigned char *>(s.c_str()), s.length());
 65         SHA1_Final(digest, &ctx);
 66 
 67         string ret = reinterpret_cast<char *>(HashPtn::pt(digest, SHA_DIGEST_LENGTH));
 68         return ret;
 69     }
 70 };
 71 
 72 struct Hash
 73 {
 74     HashPtn * m_strategy ;
 75     Hash( HashPtn * in_strategy )
 76     {
 77         m_strategy = in_strategy ;
 78     }
 79 
 80     string get_hash_( string s ) const 
 81     {
 82         return m_strategy->get_hash( s.c_str() );
 83     }
 84 } ;
 85 
 86 Hash get_algorithms_map( const string my_algorithm )
 87 {
 88     typedef map<string, Hash> algorithms_map_t;
 89     algorithms_map_t algorithms_map;
 90 
 91     MD5_hash md5;
 92     SHA1_hash sha1;
 93     Hash md5_h( &md5 );
 94     Hash sha1_h( &sha1 );
 95 
 96     algorithms_map.insert( pair <string, Hash>( "md5" , md5_h  ) );
 97     algorithms_map.insert( pair <string, Hash>( "sha1", sha1_h ) );
 98 
 99     algorithms_map_t::iterator p;
100     p = algorithms_map.find( my_algorithm );
101     if ( p != algorithms_map.end())
102     {
103         return (*p).second;
104     }
105     else 
106     {
107         throw logic_error("not found");
108     }
109 }
110 
111 int main ()
112 {
113     // 本当は引数とかでこの値を入れると思います。
114     string my_algorithm = "md5";
115     Hash h = get_algorithms_map( my_algorithm );
116     cerr << h.get_hash_("hoge") << endl;
117 
118     return 0;
119 }