I have a factory method pattern used to create classes and I'd like to validate the input parameters before proceeding to the actual creation. There are two classes that I am dealing with here, A and B, and they each have their own validation. Given that I am already passing the class type (A or B) in my creation template function, I'd like to use that type directly to tell which validation I need to use. I am considering to use template function specialization or dummy input parameter to do that, each with their own pros/cons. Please let me know if either one of them looks more reasonable, or if there are other options too. Thanks!
Oh, and I did consider making the validation as static methods of A or B, but that was not looking good because I am dealing with legacy code and moving that stuff around isn't too straightforward. I also showed this as an option below for completeness-sake though.
Template function specialization:
Pro: Able to use type passed into the FactoryCreateClass method directly for choosing validation
Con: Template method isn't being leveraged since there are only specializations
template <typename T>
void FactoryCreateClass (int, double)
(
bool bSuccess = ValidateBlock<T>(int, double);
if (bSuccess)
T* = T::CreateInstance();
)
template <typename T>
bool ValidateBlock (int double); // don't need an implementation here since
// all specialization require different validation
template <>
bool ValidateBlock<A> (int, double)
{
//do validation before creating A
}
template <>
bool ValidateBlock<B> (int, double)
{
//do validation before creating B
}
Dummy Variable:
Pro: Able to use type passed into the FactoryCreateClass method directly for choosing validation
Con: Unused dummy variable
template <typename T>
void FactoryCreateClass (int, double)
(
bool bSuccess = ValidateBlock(T /*dummy*/, int, double);
if (bSuccess)
T* = T::CreateInstance();
)
bool ValidateBlock (A/*dummy*/, int, double)
{
//do validation before creating A
}
bool ValidateBlock (B/*dummy*/, int, double)
{
//do validation before creating B
}
Static class method:
Pro: Able to use type passed into the FactoryCreateClass method directly for choosing validation
Con: Harder to make this type of change in legacy code
template <typename T>
void FactoryCreateClass (int, double)
(
bool bSuccess = T::ValidateBlock(int, double);
if (bSuccess)
T* = T::CreateInstance();
)
static bool A::ValidateBlock (int, double)
{
//do validation before creating A
}
static bool B::ValidateBlock (int, double)
{
//do validation before creating B
}
You have forgotten a third alternative: using traits.
template <typename> struct Trait;
template <>
struct Trait<A> {
static bool Validate(int, double);
};
template <>
struct Trait<B> {
static bool Validate(int, double);
};
And then:
template <typename T>
void FactoryCreateClass(int i, double d) {
bool const success = Trait<T>::Validate(i, d);
// ...
}
But of course, the real question is why not doing the validation in CreateInstance
directly ?
The most appropriate design here is to do the validation inside the CreateInstance
method, because the tasks (args validation and instance creation) are strongly coupled, and it is much more readable to have these to things together in one place.
However, it may be the case, you cannot change the code of the CreateInstance
method. Well, then I see no significant difference between using function template or dummy variable. The latter is , however, a bit more explicit and thus more readable.
By the way, an unreferenced variable is really not a big problem, you can suppress it, see Disable single warning error , search for UNREFERENCED_PARAMETER
on the page
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.