Я реализовал шаблон фабрики в C ++ несколько недель назад, используя следующее руководство: https://www.codeproject.com/Articles/363338/Factory-Pattern-in-Cplusplus
С тех пор все работало хорошо: все методы, используемые в фабричном шаблоне, возвращали один и тот же тип, а также принимали те же типы аргументов до сегодняшнего дня. Теперь мне нужно добавить новые аргументы bind в методы, которые я использую, чтобы сигнатуры методов больше не были одинаковыми.
Я использую 2 вещи и реализую третье:
1) Действия: каждое из них представлено в виде класса и содержит статический метод AAction :: ptr create (void * buff). Действия наследуются от класса AAction. Действия могут быть сериализованы с использованием их собственного внутреннего метода serialize () или десериализованы с использованием их статического метода create (buff).
Аргумент буфера содержит идентификатор и пароль, необходимые для вызова конструктора LoginAction ().
class AAction {
typedef std::unique_ptr<AAction> ptr;
};
class LoginAction : public AAction {
private:
std::string id;
std::string password;
bool authenticated;
public:
LoginAction(std::string id, std::string password);
virtual ~LoginAction() = default;
void execute();
static AAction::ptr create(const void* buffer);
};
2) ActionFactory: используется для десериализации входящих действий путем вызова соответствующего статического метода create () из правильного класса.
class ActionFactory {
typedef std::unique_ptr<AAction> (*CreateActionFn)(const void*);
typedef std::map<RawActionType, CreateActionFn> RawFactoryMap;
RawFactoryMap rawFactoryMap;
public:
ActionFactory(Authenticator& authenticator) {
this->registerMethod(RawActionType_RawLoginAction, &LoginAction::create);
this->registerMethod(RawActionType_RawLogoutAction, &LogoutAction::create);
this->registerMethod(RawActionType_RawStandAction, &StandAction::create);
}
void registerMethod(const RawActionType &rawActionType, CreateActionFn pfnCreate);
std::unique_ptr<AAction> getAction(RawActionType rawActionType, const void* buffer);
};
Действия могут быть выполнены в любое время в коде, просто вызывая метод execute () без параметров.
До этого момента все работало нормально.
Проблема в том, что мне теперь нужно добавить еще несколько параметров к действиям, которые не хранятся внутри пароля. Например, в моем случае: Аутентификатор
3) Аутентификатор, для аутентификации пользователя.
Чтобы внутри LoginAction :: execute () все, что мне нужно сделать, это вызвать
this->authenticator.authenticate(this->id, this->password).
Вот изменения, которые я сделал для этого:
Я добавил аутентификатор в конструктор LoginAction:
LoginAction(Authenticator& authenticator, std::string id, std::string password);
и поле:
Authenticator& authenticator;
Я добавил аутентификатор в метод LoginAction :: create static:
static AAction::ptr create(const void* buffer, Authenticator& authenticator);
Я изменил в конструкторе ActionFactory способ регистрации метода, используя std :: bind:
this->registerMethod(RawActions_RawLoginAction, std::bind(&LoginAction::create, std::placeholders::_1, authenticator);
Но, поскольку мои типы функций изменились, я больше не могу сохранять их в RawFactoryMap.
ошибка: недопустимое приведение типа ‘std :: _ Bind_helper () (const void , Authenticator &), const
std :: _ Placeholder <1> &, Аутентификатор &> :: type {aka
std :: _ Bind ( (std :: _ Placeholder <1>,
Аутентификатор)) (const void , Аутентификатор &)>} ’для ввода
‘ActionFactory :: CreateActionFn {он же std :: unique_ptr () (постоянный
пустота )}»
Каков наилучший способ сохранить карту функций в ActionFactory и соблюдать шаблон Factory?
Заранее спасибо, и хорошего дня!
В качестве дополнительного примечания: я открыт и был бы рад прочитать любые предложения о том, как улучшить мой код, даже для некоторых незначительных улучшений.