Лично я бы создал некоторый абстрактный интерфейс, представляющий алгоритм шифрования, с заводской функцией, берущей ключ и производящей конкретный экземпляр алгоритма шифрования с установленным ключом. Таким образом, «второй класс» здесь будет обращаться напрямую к «первому классу», но будет «третий класс», отвечающий за создание экземпляра класса. Что-то вроде:
/* Core encryption framework definitions */
class CipherInstance {
// ...
public:
virtual void encrypt(void *, size_t) = 0;
virtual void decrypt(void *, size_t) = 0;
virtual size_t blocksize() const = 0;
// ...
virtual ~CipherInstance() { }
};
class Cipher {
public:
virtual CipherInstance *instantiate(const void *key, size_t keylen) = 0;
virtual size_t minkeysize() const = 0;
virtual size_t maxkeysize() const = 0;
};
/* AES implementation */
class privateAESImpl : public Cipher { /* ... */ };
// This is the only public definition in the AES implementation. The privateAESImpl
// class is a stateless singleton, and this is the only instance. Doing this instead
// of static functions allows AES to be passed to a function taking a Cipher *
extern privateAESImpl AES;
// Much later:
CipherInstance *aes = AES.instantiate(key, keylen);
aes->encrypt(data, datalen);
// or, to be more general:
void frob(Cipher *cipher, void *key, size_t keylen, void *data, size_t datalen) {
CipherInstance *inst = cipher->instantiate(key, keylen);
inst->encrypt(data, datalen);
}
Библиотеки
C # System.Security.Cryptography
используют аналогичный подход - см., Например, System.Security.Cryptography.SymmetricAlgorithm
. Однако обратите внимание, что, поскольку C # поддерживает самоанализ, нет необходимости в фабричном классе - вместо этого есть просто статический метод, принимающий имя. В C ++ необходим полный фабричный класс.