I have a requirement to create some objects that implement a given interface, where the type of concrete implementation being created is based on an Enum value.
I run into trouble when the different concrete implementations require different parameters at runtime.
This example (C#) is fine:
public enum ProductCategory
{
Modem,
Keyboard,
Monitor
}
public class SerialNumberValidatorFactory()
{
public ISerialNumberValidator CreateValidator(ProductCategory productCategory)
{
switch (productCategory)
{
case ProductCategory.Modem:
return new ModemSerialNumberValidator();
case ProductCategory.Keyboard:
return new KeyboardSerialNumberValidator();
case ProductCategory.Monitor:
return new MonitorSerialNumberValidator();
default:
throw new ArgumentException("productType", string.Format("Product category not supported for serial number validation: {0}", productCategory))
}
}
}
However, what happens if the concrete implementations have different constructor arguments? I can't pass in all the values to the SerialNumberValidatorFactory.CreateValidator()
method, so how do I proceed?
I've heard the Abstract Factory
pattern is supposed to solve this, but I'm not sure how to implement it properly.
You can always create a Settings container to pass to the CreateValidator
method. Start with a base IValidatorSettings
, then create IModemSerialNumberValidatorSettings
etc, your CreateValidator
could then take ProductType
and IValidatorSettings
arguments.
Your concrete classes for the validators would then take their IXXXValidatorSettings
interface as the sole constructor argument.
Further to this you could then create an IValidatorSettings
factory.
I think abstract factory is a factory that creates a factory to handle a given set of types - not sure if it would apply in your scenario.
What you are using is a Factory Method pattern, what you should use is an Abstract Factory
In abstract factory, you provide a factory class for each concrete implementation:
So your code becomes: (forgive the code, but the rationale is same)
public class SerialNumberValidatorFactory
{
public static SerialNumberValidatorFactory newInstance(
ProductCategory productCategory)
{
switch (productCategory)
{
case ProductCategory.Modem:
return new ModemValidatorFactory();
....
}
}
public abstract ISerialNumberValidator createValidator();
}
public class ModemValidatorFactory extends SerialNumberValidatorFactory
{
public ISerialNumberValidator createValidator()
{
return new ModemSerialNumberValidator("model", "number");
}
}
ISerialNumberValidator = SerialNumberValidatorFactory.newInstance(productCategory).createValidator()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With