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 }